qontract-reconcile 0.10.1rc976__py3-none-any.whl → 0.10.1rc977__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.1rc976.dist-info → qontract_reconcile-0.10.1rc977.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc976.dist-info → qontract_reconcile-0.10.1rc977.dist-info}/RECORD +109 -109
- reconcile/aus/healthchecks.py +1 -1
- reconcile/aws_account_manager/integration.py +23 -21
- reconcile/aws_account_manager/reconciler.py +1 -1
- reconcile/aws_saml_idp/integration.py +5 -5
- reconcile/aws_saml_roles/integration.py +5 -5
- reconcile/aws_version_sync/utils.py +3 -3
- reconcile/cna/state.py +2 -2
- reconcile/database_access_manager.py +2 -5
- reconcile/external_resources/manager.py +3 -3
- reconcile/external_resources/model.py +1 -1
- reconcile/external_resources/secrets_sync.py +2 -2
- reconcile/external_resources/state.py +1 -1
- reconcile/gcr_mirror.py +2 -6
- reconcile/jira_permissions_validator.py +4 -4
- reconcile/ldap_groups/integration.py +4 -7
- reconcile/ocm_internal_notifications/integration.py +2 -2
- reconcile/openshift_base.py +14 -14
- reconcile/openshift_cluster_bots.py +1 -1
- reconcile/openshift_clusterrolebindings.py +9 -10
- reconcile/openshift_namespace_labels.py +2 -2
- reconcile/openshift_namespaces.py +1 -1
- reconcile/openshift_resources_base.py +9 -9
- reconcile/openshift_rolebindings.py +8 -11
- reconcile/openshift_saas_deploy_trigger_base.py +8 -5
- reconcile/oum/base.py +1 -1
- reconcile/quay_mirror.py +3 -10
- reconcile/queries.py +1 -1
- reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py +2 -2
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +0 -1
- reconcile/skupper_network/integration.py +3 -1
- reconcile/skupper_network/site_controller.py +8 -8
- reconcile/slack_usergroups.py +10 -10
- reconcile/status_board.py +1 -1
- reconcile/statuspage/status.py +1 -3
- reconcile/terraform_cloudflare_dns.py +2 -3
- reconcile/terraform_cloudflare_users.py +2 -3
- reconcile/terraform_repo.py +5 -3
- reconcile/terraform_resources.py +16 -16
- reconcile/terraform_tgw_attachments.py +6 -6
- reconcile/terraform_vpc_peerings.py +8 -8
- reconcile/terraform_vpc_resources/integration.py +1 -1
- reconcile/test/test_aws_cloudwatch_log_retention.py +2 -5
- reconcile/test/test_github_org.py +18 -16
- reconcile/test/test_github_repo_invites.py +10 -10
- reconcile/test/test_integrations_manager.py +11 -11
- reconcile/test/test_ocm_additional_routers.py +6 -6
- reconcile/test/test_ocm_clusters.py +1 -0
- reconcile/test/test_ocm_update_recommended_version.py +2 -2
- reconcile/test/test_openshift_serviceaccount_tokens.py +5 -5
- reconcile/test/test_openshift_tekton_resources.py +3 -3
- reconcile/test/test_saasherder.py +48 -48
- reconcile/test/test_sql_query.py +1 -1
- reconcile/test/test_terraform_cloudflare_resources.py +14 -14
- reconcile/test/test_terraform_cloudflare_users.py +4 -4
- reconcile/test/test_terraform_resources.py +32 -32
- reconcile/test/test_terraform_tgw_attachments.py +5 -5
- reconcile/typed_queries/saas_files.py +1 -1
- reconcile/unleash_feature_toggles/integration.py +2 -2
- reconcile/utils/aggregated_list.py +1 -1
- reconcile/utils/aws_api.py +1 -1
- reconcile/utils/aws_api_typed/iam.py +4 -2
- reconcile/utils/aws_api_typed/service_quotas.py +2 -2
- reconcile/utils/binary.py +1 -1
- reconcile/utils/clusterhealth/telemeter.py +5 -3
- reconcile/utils/config.py +4 -2
- reconcile/utils/expiration.py +1 -1
- reconcile/utils/external_resources.py +4 -7
- reconcile/utils/git.py +1 -3
- reconcile/utils/gitlab_api.py +1 -4
- reconcile/utils/gql.py +9 -8
- reconcile/utils/helm.py +1 -1
- reconcile/utils/imap_client.py +3 -1
- reconcile/utils/internal_groups/client.py +1 -1
- reconcile/utils/jinja2/utils.py +4 -4
- reconcile/utils/jobcontroller/models.py +2 -2
- reconcile/utils/jump_host.py +1 -1
- reconcile/utils/ldap_client.py +1 -1
- reconcile/utils/merge_request_manager/merge_request_manager.py +1 -4
- reconcile/utils/models.py +2 -5
- reconcile/utils/oc.py +18 -28
- reconcile/utils/ocm/ocm.py +3 -1
- reconcile/utils/ocm/products.py +2 -2
- reconcile/utils/ocm/search_filters.py +4 -11
- reconcile/utils/ocm_base_client.py +1 -4
- reconcile/utils/openshift_resource.py +12 -19
- reconcile/utils/quay_api.py +1 -3
- reconcile/utils/repo_owners.py +2 -8
- reconcile/utils/runtime/runner.py +1 -1
- reconcile/utils/saasherder/saasherder.py +4 -4
- reconcile/utils/secret_reader.py +2 -2
- reconcile/utils/slack_api.py +1 -1
- reconcile/utils/sqs_gateway.py +1 -1
- reconcile/utils/state.py +4 -4
- reconcile/utils/terraform/config_client.py +1 -1
- reconcile/utils/terraform_client.py +2 -2
- reconcile/utils/terrascript_aws_client.py +13 -23
- reconcile/utils/three_way_diff_strategy.py +3 -9
- reconcile/utils/unleash/client.py +2 -2
- reconcile/utils/vault.py +11 -14
- reconcile/utils/vcs.py +1 -1
- reconcile/vault_replication.py +1 -1
- tools/app_interface_reporter.py +2 -3
- tools/qontract_cli.py +1 -1
- {qontract_reconcile-0.10.1rc976.dist-info → qontract_reconcile-0.10.1rc977.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc976.dist-info → qontract_reconcile-0.10.1rc977.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc976.dist-info → qontract_reconcile-0.10.1rc977.dist-info}/top_level.txt +0 -0
@@ -46,7 +46,7 @@ class InternalGroupsApi:
|
|
46
46
|
resp.raise_for_status()
|
47
47
|
except requests.exceptions.HTTPError as e:
|
48
48
|
if e.response is not None and e.response.status_code == 404:
|
49
|
-
raise NotFound
|
49
|
+
raise NotFound(e.response.text) from e
|
50
50
|
raise
|
51
51
|
|
52
52
|
def __enter__(self) -> Self:
|
reconcile/utils/jinja2/utils.py
CHANGED
@@ -175,9 +175,9 @@ def lookup_secret(
|
|
175
175
|
except (SecretNotFound, SecretFieldNotFound) as e:
|
176
176
|
if allow_not_found:
|
177
177
|
return None
|
178
|
-
raise FetchSecretError(e)
|
178
|
+
raise FetchSecretError(e) from None
|
179
179
|
except Exception as e:
|
180
|
-
raise FetchSecretError(e)
|
180
|
+
raise FetchSecretError(e) from e
|
181
181
|
|
182
182
|
|
183
183
|
def process_jinja2_template(
|
@@ -221,12 +221,12 @@ def process_jinja2_template(
|
|
221
221
|
})
|
222
222
|
if "_template_mocks" in vars:
|
223
223
|
for k, v in vars["_template_mocks"].items():
|
224
|
-
vars[k] = lambda *args, **kwargs: v
|
224
|
+
vars[k] = lambda *args, **kwargs: v # noqa: B023
|
225
225
|
try:
|
226
226
|
template = compile_jinja2_template(body, extra_curly, template_render_options)
|
227
227
|
r = template.render(vars)
|
228
228
|
except Exception as e:
|
229
|
-
raise Jinja2TemplateError(e)
|
229
|
+
raise Jinja2TemplateError(e) from None
|
230
230
|
return r
|
231
231
|
|
232
232
|
|
@@ -160,7 +160,7 @@ class K8sJob(ABC):
|
|
160
160
|
)
|
161
161
|
),
|
162
162
|
)
|
163
|
-
for secret_key_name in self.secret_data()
|
163
|
+
for secret_key_name in self.secret_data()
|
164
164
|
]
|
165
165
|
|
166
166
|
def scripts_volume_mount(self, directory: str) -> V1VolumeMount:
|
@@ -189,7 +189,7 @@ class K8sJob(ABC):
|
|
189
189
|
key=script_name,
|
190
190
|
path=script_name,
|
191
191
|
)
|
192
|
-
for script_name in self.scripts()
|
192
|
+
for script_name in self.scripts()
|
193
193
|
],
|
194
194
|
),
|
195
195
|
)
|
reconcile/utils/jump_host.py
CHANGED
@@ -90,7 +90,7 @@ class JumpHostSSH(JumpHostBase):
|
|
90
90
|
try:
|
91
91
|
known_hosts = self._gql_api.get_resource(known_hosts_path)
|
92
92
|
except gql.GqlGetResourceError as e:
|
93
|
-
raise FetchResourceError(str(e))
|
93
|
+
raise FetchResourceError(str(e)) from None
|
94
94
|
return known_hosts["content"]
|
95
95
|
|
96
96
|
def _init_known_hosts_file(self) -> None:
|
reconcile/utils/ldap_client.py
CHANGED
@@ -33,7 +33,7 @@ class LdapClient:
|
|
33
33
|
_, _, results, _ = self.connection.search(
|
34
34
|
self.base_dn, f"(&(objectclass=person)(|{user_filter}))", attributes=["uid"]
|
35
35
|
)
|
36
|
-
return
|
36
|
+
return {r["attributes"]["uid"][0] for r in results}
|
37
37
|
|
38
38
|
def get_group_members(self, groups_dns: set[str]) -> dict[str, set[str]]:
|
39
39
|
"""
|
@@ -43,10 +43,7 @@ class MergeRequestManagerBase(Generic[T]):
|
|
43
43
|
) -> OpenMergeRequest | None:
|
44
44
|
for mr in self._open_mrs:
|
45
45
|
mr_info_dict = mr.mr_info.dict()
|
46
|
-
if all(
|
47
|
-
mr_info_dict.get(k) == expected_data.get(k)
|
48
|
-
for k in expected_data.keys()
|
49
|
-
):
|
46
|
+
if all(mr_info_dict.get(k) == expected_data.get(k) for k in expected_data):
|
50
47
|
return mr
|
51
48
|
|
52
49
|
return None
|
reconcile/utils/models.py
CHANGED
@@ -94,10 +94,7 @@ class CSV(list[str]):
|
|
94
94
|
|
95
95
|
@classmethod
|
96
96
|
def validate(cls, value: str) -> list[str]:
|
97
|
-
if not value
|
98
|
-
items = []
|
99
|
-
else:
|
100
|
-
items = value.split(",")
|
97
|
+
items = [] if not value else value.split(",")
|
101
98
|
return items
|
102
99
|
|
103
100
|
@classmethod
|
@@ -123,4 +120,4 @@ def cron_validator(value: str) -> str:
|
|
123
120
|
croniter(value)
|
124
121
|
return value
|
125
122
|
except ValueError as e:
|
126
|
-
raise ValueError(f"Invalid cron expression: {e}")
|
123
|
+
raise ValueError(f"Invalid cron expression: {e}") from None
|
reconcile/utils/oc.py
CHANGED
@@ -231,14 +231,10 @@ def equal_spec_template(t1: dict, t2: dict) -> bool:
|
|
231
231
|
"""Compare two spec.templates."""
|
232
232
|
t1_copy = copy.deepcopy(t1)
|
233
233
|
t2_copy = copy.deepcopy(t2)
|
234
|
-
|
234
|
+
with suppress(KeyError):
|
235
235
|
del t1_copy["metadata"]["labels"]["pod-template-hash"]
|
236
|
-
|
237
|
-
pass
|
238
|
-
try:
|
236
|
+
with suppress(KeyError):
|
239
237
|
del t2_copy["metadata"]["labels"]["pod-template-hash"]
|
240
|
-
except KeyError:
|
241
|
-
pass
|
242
238
|
return t1_copy == t2_copy
|
243
239
|
|
244
240
|
|
@@ -740,11 +736,11 @@ class OCCli: # pylint: disable=too-many-public-methods
|
|
740
736
|
cmd = ["logs", "--all-containers=true", "-n", namespace, f"job/{name}"]
|
741
737
|
if follow:
|
742
738
|
cmd.append("-f")
|
743
|
-
|
739
|
+
|
744
740
|
if isinstance(output, TextIOWrapper):
|
745
741
|
output_file = output
|
746
742
|
else:
|
747
|
-
output_file = open(os.path.join(output, name), "w", encoding="locale")
|
743
|
+
output_file = open(os.path.join(output, name), "w", encoding="locale") # noqa: SIM115
|
748
744
|
|
749
745
|
if wait_for_logs_process:
|
750
746
|
subprocess.run(self.oc_base_cmd + cmd, stdout=output_file, check=False)
|
@@ -1138,7 +1134,7 @@ class OCCli: # pylint: disable=too-many-public-methods
|
|
1138
1134
|
try:
|
1139
1135
|
out_json = json.loads(out)
|
1140
1136
|
except ValueError as e:
|
1141
|
-
raise JSONParsingError(out + "\n" + str(e))
|
1137
|
+
raise JSONParsingError(out + "\n" + str(e)) from e
|
1142
1138
|
|
1143
1139
|
return out_json
|
1144
1140
|
|
@@ -1280,13 +1276,13 @@ class OCNative(OCCli):
|
|
1280
1276
|
|
1281
1277
|
@retry(exceptions=(ServerTimeoutError, InternalServerError, ForbiddenError))
|
1282
1278
|
def _get_client(self, server, token):
|
1283
|
-
opts =
|
1284
|
-
api_key
|
1285
|
-
host
|
1286
|
-
verify_ssl
|
1279
|
+
opts = {
|
1280
|
+
"api_key": {"authorization": f"Bearer {token}"},
|
1281
|
+
"host": server,
|
1282
|
+
"verify_ssl": False,
|
1287
1283
|
# default timeout seems to be 1+ minutes
|
1288
|
-
retries
|
1289
|
-
|
1284
|
+
"retries": 5,
|
1285
|
+
}
|
1290
1286
|
if self.jump_host:
|
1291
1287
|
# the ports could be parameterized, but at this point
|
1292
1288
|
# we only have need of 1 tunnel for 1 service
|
@@ -1307,7 +1303,7 @@ class OCNative(OCCli):
|
|
1307
1303
|
try:
|
1308
1304
|
return DynamicClient(k8s_client, discoverer=OpenshiftLazyDiscoverer)
|
1309
1305
|
except urllib3.exceptions.MaxRetryError as e:
|
1310
|
-
raise StatusCodeError(f"[{self.server}]: {e}")
|
1306
|
+
raise StatusCodeError(f"[{self.server}]: {e}") from None
|
1311
1307
|
|
1312
1308
|
def _get_obj_client(self, kind, group_version):
|
1313
1309
|
key = f"{kind}.{group_version}"
|
@@ -1380,7 +1376,7 @@ class OCNative(OCCli):
|
|
1380
1376
|
except NotFoundError as e:
|
1381
1377
|
if allow_not_found:
|
1382
1378
|
return {}
|
1383
|
-
raise StatusCodeError(f"[{self.server}]: {e}")
|
1379
|
+
raise StatusCodeError(f"[{self.server}]: {e}") from None
|
1384
1380
|
|
1385
1381
|
def get_all(self, kind, all_namespaces=False):
|
1386
1382
|
k, group_version = self._parse_kind(kind)
|
@@ -1388,7 +1384,7 @@ class OCNative(OCCli):
|
|
1388
1384
|
try:
|
1389
1385
|
return obj_client.get(_request_timeout=REQUEST_TIMEOUT).to_dict()
|
1390
1386
|
except NotFoundError as e:
|
1391
|
-
raise StatusCodeError(f"[{self.server}]: {e}")
|
1387
|
+
raise StatusCodeError(f"[{self.server}]: {e}") from None
|
1392
1388
|
|
1393
1389
|
|
1394
1390
|
OCClient = OCNative | OCCli
|
@@ -1640,10 +1636,7 @@ class OC_Map:
|
|
1640
1636
|
)
|
1641
1637
|
return
|
1642
1638
|
|
1643
|
-
if self.use_jump_host
|
1644
|
-
jump_host = cluster_info.get("jumpHost")
|
1645
|
-
else:
|
1646
|
-
jump_host = None
|
1639
|
+
jump_host = cluster_info.get("jumpHost") if self.use_jump_host else None
|
1647
1640
|
if jump_host:
|
1648
1641
|
self.set_jh_ports(jump_host)
|
1649
1642
|
try:
|
@@ -1846,17 +1839,14 @@ class OpenshiftLazyDiscoverer(LazyDiscoverer):
|
|
1846
1839
|
]
|
1847
1840
|
# If there are multiple matches, prefer non-List kinds
|
1848
1841
|
if len(results) > 1 and not all( # pylint: disable=R1729
|
1849
|
-
|
1842
|
+
isinstance(x, ResourceList) for x in results
|
1850
1843
|
):
|
1851
1844
|
results = [
|
1852
1845
|
result for result in results if not isinstance(result, ResourceList)
|
1853
1846
|
]
|
1854
1847
|
# if multiple resources are found that share a GVK, prefer the one with the most supported verbs
|
1855
|
-
if (
|
1856
|
-
len(results)
|
1857
|
-
and len(set((x.group_version, x.kind) for x in results)) == 1
|
1858
|
-
):
|
1859
|
-
if len(set(len(x.verbs) for x in results)) != 1:
|
1848
|
+
if len(results) > 1 and len({(x.group_version, x.kind) for x in results}) == 1:
|
1849
|
+
if len({len(x.verbs) for x in results}) != 1:
|
1860
1850
|
results = [max(results, key=lambda x: len(x.verbs))]
|
1861
1851
|
if len(results) == 1:
|
1862
1852
|
return results[0]
|
reconcile/utils/ocm/ocm.py
CHANGED
@@ -828,7 +828,9 @@ class OCM: # pylint: disable=too-many-public-methods
|
|
828
828
|
try:
|
829
829
|
re.compile(b)
|
830
830
|
except re.error:
|
831
|
-
raise TypeError(
|
831
|
+
raise TypeError(
|
832
|
+
f"blocked version is not a valid regex expression: {b}"
|
833
|
+
) from None
|
832
834
|
|
833
835
|
@retry(max_attempts=10)
|
834
836
|
def _do_get_request(self, api: str, params: Mapping[str, str]) -> dict[str, Any]:
|
reconcile/utils/ocm/products.py
CHANGED
@@ -354,7 +354,7 @@ class OCMProductRosa(OCMProduct):
|
|
354
354
|
e.cleanup()
|
355
355
|
raise OCMValidationException(
|
356
356
|
f"last 10 lines from failed cluster creation job...\n\n{logs}"
|
357
|
-
)
|
357
|
+
) from None
|
358
358
|
|
359
359
|
def update_cluster(
|
360
360
|
self,
|
@@ -629,7 +629,7 @@ class OCMProductHypershift(OCMProduct):
|
|
629
629
|
e.cleanup()
|
630
630
|
raise OCMValidationException(
|
631
631
|
f"last 10 lines from failed cluster creation job...\n\n{logs}"
|
632
|
-
)
|
632
|
+
) from None
|
633
633
|
|
634
634
|
def update_cluster(
|
635
635
|
self,
|
@@ -56,7 +56,7 @@ class ListCondition(ABC, FilterCondition):
|
|
56
56
|
raise InvalidFilterError(f"Cannot merge {self} with {other}")
|
57
57
|
return type(self)(
|
58
58
|
key=self.key,
|
59
|
-
values=sorted(
|
59
|
+
values=sorted(set(self.values + other.values)),
|
60
60
|
)
|
61
61
|
|
62
62
|
|
@@ -72,9 +72,7 @@ class EqCondition(ListCondition):
|
|
72
72
|
def render(self) -> str:
|
73
73
|
if len(self.values) == 1:
|
74
74
|
return f"{self.key}='{self._escape_value(self.values[0])}'"
|
75
|
-
quoted_values = ",".join(
|
76
|
-
map(lambda x: f"'{self._escape_value(x)}'", self.values)
|
77
|
-
)
|
75
|
+
quoted_values = ",".join(f"'{self._escape_value(x)}'" for x in self.values)
|
78
76
|
return f"{self.key} in ({quoted_values})"
|
79
77
|
|
80
78
|
def _escape_value(self, value: Any) -> str:
|
@@ -93,9 +91,7 @@ class LikeCondition(ListCondition):
|
|
93
91
|
def render(self) -> str:
|
94
92
|
if len(self.values) == 1:
|
95
93
|
return f"{self.key} like '{self.values[0]}'"
|
96
|
-
quoted_values = " or ".join(
|
97
|
-
map(lambda x: f"{self.key} like '{x}'", self.values)
|
98
|
-
)
|
94
|
+
quoted_values = " or ".join(f"{self.key} like '{x}'" for x in self.values)
|
99
95
|
if len(self.values) > 1:
|
100
96
|
return f"({quoted_values})"
|
101
97
|
return quoted_values
|
@@ -284,10 +280,7 @@ class Filter:
|
|
284
280
|
are None or empty, the condition is not added.
|
285
281
|
"""
|
286
282
|
if values:
|
287
|
-
if isinstance(values, list)
|
288
|
-
value_list = values
|
289
|
-
else:
|
290
|
-
value_list = list(values)
|
283
|
+
value_list = values if isinstance(values, list) else list(values)
|
291
284
|
value_list.sort()
|
292
285
|
return self.add_condition(EqCondition(key, value_list))
|
293
286
|
return self
|
@@ -84,10 +84,7 @@ class OCMBaseClient:
|
|
84
84
|
max_page_size: int = 100,
|
85
85
|
max_pages: int | None = None,
|
86
86
|
) -> Generator[dict[str, Any], None, None]:
|
87
|
-
if not params
|
88
|
-
params_copy = {}
|
89
|
-
else:
|
90
|
-
params_copy = params.copy()
|
87
|
+
params_copy = {} if not params else params.copy()
|
91
88
|
params_copy["size"] = max_page_size
|
92
89
|
|
93
90
|
while True:
|
@@ -1,4 +1,6 @@
|
|
1
|
+
# ruff: noqa: SIM114
|
1
2
|
import base64
|
3
|
+
import contextlib
|
2
4
|
import copy
|
3
5
|
import datetime
|
4
6
|
import hashlib
|
@@ -172,28 +174,22 @@ class OpenshiftResource:
|
|
172
174
|
"uid",
|
173
175
|
"fieldRef",
|
174
176
|
]
|
175
|
-
|
176
|
-
return True
|
177
|
-
return False
|
177
|
+
return val in ignorable_fields
|
178
178
|
|
179
179
|
@staticmethod
|
180
180
|
def ignorable_key_value_pair(key, val):
|
181
181
|
ignorable_key_value_pair = {"annotations": None, "divisor": "0"}
|
182
|
-
|
183
|
-
|
184
|
-
|
182
|
+
return bool(
|
183
|
+
key in ignorable_key_value_pair and ignorable_key_value_pair[key] == val
|
184
|
+
)
|
185
185
|
|
186
186
|
@staticmethod
|
187
187
|
def cpu_equal(val1, val2):
|
188
188
|
# normalize both to string
|
189
|
-
|
189
|
+
with contextlib.suppress(Exception):
|
190
190
|
val1 = f"{int(float(val1) * 1000)}m"
|
191
|
-
|
192
|
-
pass
|
193
|
-
try:
|
191
|
+
with contextlib.suppress(Exception):
|
194
192
|
val2 = f"{int(float(val2) * 1000)}m"
|
195
|
-
except Exception:
|
196
|
-
pass
|
197
193
|
return val1 == val2
|
198
194
|
|
199
195
|
@staticmethod
|
@@ -240,11 +236,11 @@ class OpenshiftResource:
|
|
240
236
|
|
241
237
|
def verify_valid_k8s_object(self):
|
242
238
|
try:
|
243
|
-
self.name
|
244
|
-
self.kind
|
239
|
+
assert self.name
|
240
|
+
assert self.kind
|
245
241
|
except (KeyError, TypeError) as e:
|
246
242
|
msg = f"resource invalid data ({e.__class__.__name__}). details: {self.error_details}"
|
247
|
-
raise ConstructResourceError(msg)
|
243
|
+
raise ConstructResourceError(msg) from None
|
248
244
|
|
249
245
|
if self.kind not in {
|
250
246
|
"Role",
|
@@ -348,10 +344,7 @@ class OpenshiftResource:
|
|
348
344
|
openshift_resource: new OpenshiftResource object with
|
349
345
|
annotations.
|
350
346
|
"""
|
351
|
-
if canonicalize
|
352
|
-
body = self.canonicalize(self.body)
|
353
|
-
else:
|
354
|
-
body = self.body
|
347
|
+
body = self.canonicalize(self.body) if canonicalize else self.body
|
355
348
|
|
356
349
|
sha256sum = self.calculate_sha256sum(self.serialize(body))
|
357
350
|
|
reconcile/utils/quay_api.py
CHANGED
@@ -57,9 +57,7 @@ class QuayApi:
|
|
57
57
|
def user_exists(self, user):
|
58
58
|
url = f"{self.api_url}/users/{user}"
|
59
59
|
r = requests.get(url, headers=self.auth_header, timeout=self._timeout)
|
60
|
-
|
61
|
-
return False
|
62
|
-
return True
|
60
|
+
return r.ok
|
63
61
|
|
64
62
|
def remove_user_from_team(self, user, team):
|
65
63
|
"""Deletes an user from a team.
|
reconcile/utils/repo_owners.py
CHANGED
@@ -194,15 +194,9 @@ class RepoOwners:
|
|
194
194
|
@staticmethod
|
195
195
|
def _set_to_sorted_list(owners):
|
196
196
|
approvers = owners["approvers"]
|
197
|
-
if approvers
|
198
|
-
sorted_approvers = sorted(approvers)
|
199
|
-
else:
|
200
|
-
sorted_approvers = []
|
197
|
+
sorted_approvers = sorted(approvers) if approvers else []
|
201
198
|
|
202
199
|
reviewers = owners["reviewers"]
|
203
|
-
if reviewers
|
204
|
-
sorted_reviewers = sorted(reviewers)
|
205
|
-
else:
|
206
|
-
sorted_reviewers = []
|
200
|
+
sorted_reviewers = sorted(reviewers) if reviewers else []
|
207
201
|
|
208
202
|
return {"approvers": sorted_approvers, "reviewers": sorted_reviewers}
|
@@ -213,7 +213,7 @@ def _integration_dry_run(
|
|
213
213
|
return_exceptions=True,
|
214
214
|
)
|
215
215
|
|
216
|
-
for shard, result in zip(affected_shard_list, results):
|
216
|
+
for shard, result in zip(affected_shard_list, results, strict=False):
|
217
217
|
if _is_task_result_an_error(result):
|
218
218
|
logging.error(f"Failed to run integration shard {shard}: {result}")
|
219
219
|
failed_shards_count = sum(1 for _ in filter(_is_task_result_an_error, results))
|
@@ -698,11 +698,11 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
698
698
|
return namespaces
|
699
699
|
|
700
700
|
def _collect_repo_urls(self) -> set[str]:
|
701
|
-
return
|
701
|
+
return {
|
702
702
|
rt.url
|
703
703
|
for saas_file in self.saas_files
|
704
704
|
for rt in saas_file.resource_templates
|
705
|
-
|
705
|
+
}
|
706
706
|
|
707
707
|
@staticmethod
|
708
708
|
def _get_file_contents_github(repo: Repository, path: str, commit_sha: str) -> str:
|
@@ -1189,8 +1189,8 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1189
1189
|
creds = self.secret_reader.read_all_secret(saas_file.authentication.image)
|
1190
1190
|
required_docker_config_keys = [".dockerconfigjson"]
|
1191
1191
|
required_keys_basic_auth = ["user", "token"]
|
1192
|
-
ok = all(k in creds
|
1193
|
-
k in creds
|
1192
|
+
ok = all(k in creds for k in required_keys_basic_auth) or all(
|
1193
|
+
k in creds for k in required_docker_config_keys
|
1194
1194
|
)
|
1195
1195
|
if not ok:
|
1196
1196
|
logging.warning(
|
reconcile/utils/secret_reader.py
CHANGED
@@ -164,7 +164,7 @@ class VaultSecretReader(SecretReaderBase):
|
|
164
164
|
except Forbidden:
|
165
165
|
raise VaultForbidden(
|
166
166
|
f"permission denied reading vault secret " f"at {path}"
|
167
|
-
)
|
167
|
+
) from None
|
168
168
|
except vault.SecretNotFound as e:
|
169
169
|
raise SecretNotFound(*e.args) from e
|
170
170
|
return data
|
@@ -316,7 +316,7 @@ class SecretReader(SecretReaderBase):
|
|
316
316
|
except Forbidden:
|
317
317
|
raise VaultForbidden(
|
318
318
|
f"permission denied reading vault secret " f"at {path}"
|
319
|
-
)
|
319
|
+
) from None
|
320
320
|
except vault.SecretNotFound as e:
|
321
321
|
raise SecretNotFound(*e.args) from e
|
322
322
|
else:
|
reconcile/utils/slack_api.py
CHANGED
@@ -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 UserNotFoundException(e.response["error"])
|
401
|
+
raise UserNotFoundException(e.response["error"]) from None
|
402
402
|
raise
|
403
403
|
|
404
404
|
return result["user"]["id"]
|
reconcile/utils/sqs_gateway.py
CHANGED
@@ -13,7 +13,7 @@ class SQSGateway:
|
|
13
13
|
"""Wrapper around SQS AWS SDK"""
|
14
14
|
|
15
15
|
def __init__(self, accounts, secret_reader: SecretReader):
|
16
|
-
queue_url = os.environ.get("gitlab_pr_submitter_queue_url")
|
16
|
+
queue_url = os.environ.get("gitlab_pr_submitter_queue_url") # noqa: SIM112
|
17
17
|
if not queue_url:
|
18
18
|
raise SQSGatewayInitError(
|
19
19
|
"when /app-interface/app-interface-settings-1.yml#mergeRequestGateway "
|
reconcile/utils/state.py
CHANGED
@@ -251,7 +251,7 @@ class State:
|
|
251
251
|
except ClientError as details:
|
252
252
|
raise StateInaccessibleException(
|
253
253
|
f"Bucket {self.bucket} is not accessible - {str(details)}"
|
254
|
-
)
|
254
|
+
) from None
|
255
255
|
|
256
256
|
def __enter__(self) -> Self:
|
257
257
|
return self
|
@@ -302,7 +302,7 @@ class State:
|
|
302
302
|
raise StateInaccessibleException(
|
303
303
|
f"Can not access state key {key_path} "
|
304
304
|
f"in bucket {self.bucket} - {str(details)}"
|
305
|
-
)
|
305
|
+
) from None
|
306
306
|
|
307
307
|
def ls(self) -> list[str]:
|
308
308
|
"""
|
@@ -407,10 +407,10 @@ class State:
|
|
407
407
|
return json.loads(response["Body"].read())
|
408
408
|
except ClientError as details:
|
409
409
|
if details.response["Error"]["Code"] == "NoSuchKey":
|
410
|
-
raise KeyError(item)
|
410
|
+
raise KeyError(item) from None
|
411
411
|
raise
|
412
412
|
except json.decoder.JSONDecodeError:
|
413
|
-
raise KeyError(item)
|
413
|
+
raise KeyError(item) from None
|
414
414
|
|
415
415
|
def __setitem__(self, key: str, value: Any) -> None:
|
416
416
|
self._set(key, value)
|
@@ -84,7 +84,7 @@ class TerraformConfigClientCollection:
|
|
84
84
|
except KeyError:
|
85
85
|
raise ClientNotRegisteredError(
|
86
86
|
f"There aren't any clients registered with the account name: {spec.provisioner_name}"
|
87
|
-
)
|
87
|
+
) from None
|
88
88
|
self.resource_spec_inventory[spec.id_object()] = spec
|
89
89
|
|
90
90
|
def populate_resources(self) -> None:
|
@@ -407,7 +407,7 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
407
407
|
f"[{account_name}] expiration not does not match "
|
408
408
|
f"date format {DATE_FORMAT}. details: "
|
409
409
|
f"type: {da['type']}, name: {da['name']}"
|
410
|
-
)
|
410
|
+
) from None
|
411
411
|
if (
|
412
412
|
resource_type == da["type"]
|
413
413
|
and resource_name == da["name"]
|
@@ -585,7 +585,7 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
585
585
|
secret_copy["db.password"] = replica_src_password
|
586
586
|
|
587
587
|
# clean metadata
|
588
|
-
for key in secret
|
588
|
+
for key in secret:
|
589
589
|
if integration_prefix in key:
|
590
590
|
secret_copy.pop(key)
|
591
591
|
|