qontract-reconcile 0.10.1rc830__py3-none-any.whl → 0.10.1rc832__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.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/RECORD +9 -9
- reconcile/cli.py +14 -1
- reconcile/terraform_vpc_peerings.py +121 -55
- reconcile/test/test_terraform_vpc_peerings.py +47 -49
- reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +136 -79
- {qontract_reconcile-0.10.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc832
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Home-page: https://github.com/app-sre/qontract-reconcile
|
6
6
|
Author: Red Hat App-SRE Team
|
{qontract_reconcile-0.10.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/RECORD
RENAMED
@@ -10,7 +10,7 @@ reconcile/aws_iam_password_reset.py,sha256=NwErtrqgBiXr7eGCAHdtGGOx0S7-4JnSc29Ie
|
|
10
10
|
reconcile/aws_support_cases_sos.py,sha256=Jk6_XjDeJSYxgRGqcEAOcynt9qJF2r5HPIPcSKmoBv8,2974
|
11
11
|
reconcile/blackbox_exporter_endpoint_monitoring.py,sha256=W_VJagnsJR1v5oqjlI3RJJE0_nhtJ0m81RS8zWA5u5c,3538
|
12
12
|
reconcile/checkpoint.py,sha256=R2WFXUXLTB4sWMi4GeA4eegsuf_1-Q4vH8M0Toh3Ij4,5036
|
13
|
-
reconcile/cli.py,sha256=
|
13
|
+
reconcile/cli.py,sha256=bRYr5vnUstP3dkRmt3NOyCaA4n-1xIxQU6vooISgFTk,102404
|
14
14
|
reconcile/closedbox_endpoint_monitoring_base.py,sha256=SMhkcQqprWvThrIJa3U_3uh5w1h-alleW1QnCJFY4Qw,4909
|
15
15
|
reconcile/cluster_deployment_mapper.py,sha256=2Ah-nu-Mdig0pjuiZl_XLrmVAjYzFjORR3dMlCgkmw0,2352
|
16
16
|
reconcile/dashdotdb_base.py,sha256=R2JuwiXAEYAFiCtnztM_IIr1rtVzPpaWAmgxuDa2FgY,4813
|
@@ -115,7 +115,7 @@ reconcile/terraform_repo.py,sha256=xkp5EiRQ7cz-IquXiBq5plvBQLf910tqywKK0B_QlPM,1
|
|
115
115
|
reconcile/terraform_resources.py,sha256=BN8XuJwjOt1ztruEAHydkd0YiBlb3fHZ7n0snZtRhck,19356
|
116
116
|
reconcile/terraform_tgw_attachments.py,sha256=S5IP7RmnVuVSOIPXFlUX2srGBrBBeH2uM4J6ewHCvOQ,18797
|
117
117
|
reconcile/terraform_users.py,sha256=9rgbM572LfmOSnV3uCP20G_Cw6T7due94g8rhhiz904,10225
|
118
|
-
reconcile/terraform_vpc_peerings.py,sha256=
|
118
|
+
reconcile/terraform_vpc_peerings.py,sha256=WhGvDHwllM36yTJPE5EzQ1Z0Oc-tT9ksXbBn5cpFBBg,27676
|
119
119
|
reconcile/vault_replication.py,sha256=79GZ_kCimPoQcxkdhkWTQxPOAa46E0mNhf05s_Mk5so,17385
|
120
120
|
reconcile/vpc_peerings_validator.py,sha256=Kv22HJVlTW9l9GB2eXwjPWqdDbr_VuvQBNPttox6s5o,7177
|
121
121
|
reconcile/aus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -537,8 +537,8 @@ reconcile/test/test_terraform_repo.py,sha256=j9mLfwiK707U2KRxYpvzAbOYywk__pL9SXA
|
|
537
537
|
reconcile/test/test_terraform_resources.py,sha256=EFCqPI5_G8hPRh1zmnU91o8wMeT2qK1CabDUa_X1rSk,15283
|
538
538
|
reconcile/test/test_terraform_tgw_attachments.py,sha256=rHZHUtDxewpKsRj3nfm2bZ2JoQ4CWiN2nQM-SWkMopg,41047
|
539
539
|
reconcile/test/test_terraform_users.py,sha256=XOAfGvITCJPI1LTlISmHbA4ONMQMkxYUMTsny7pQCFw,4319
|
540
|
-
reconcile/test/test_terraform_vpc_peerings.py,sha256=
|
541
|
-
reconcile/test/test_terraform_vpc_peerings_build_desired_state.py,sha256=
|
540
|
+
reconcile/test/test_terraform_vpc_peerings.py,sha256=Btl0ym7NmO2QFST9Xviz4OO1RjJuhCp1Xhix5A3e_HQ,20822
|
541
|
+
reconcile/test/test_terraform_vpc_peerings_build_desired_state.py,sha256=7VAFVbjlnnUJoOkZ4ApDc1lHFj38Zj4yrbDKvWkqWXE,49545
|
542
542
|
reconcile/test/test_three_way_diff_strategy.py,sha256=0QY2hzOrTVnQxDFbdOJBOIIHEKKOA5RmGftT0QXABeY,3697
|
543
543
|
reconcile/test/test_utils_jinja2.py,sha256=TpzQlpFnLGzNEZp5WOh0o7AuBiGEktqO4MuwiiJW2YY,3895
|
544
544
|
reconcile/test/test_vault_replication.py,sha256=wlc4jm9f8P641UvvxIFFFc5_unJysNkOVrKJscjhQr0,16867
|
@@ -812,8 +812,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
812
812
|
tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jrss,4941
|
813
813
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
814
814
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
815
|
-
qontract_reconcile-0.10.
|
816
|
-
qontract_reconcile-0.10.
|
817
|
-
qontract_reconcile-0.10.
|
818
|
-
qontract_reconcile-0.10.
|
819
|
-
qontract_reconcile-0.10.
|
815
|
+
qontract_reconcile-0.10.1rc832.dist-info/METADATA,sha256=7yMOQ62RfKBicCBhKjtcwL8CN6tJUQvFOH6K5lBcDP0,2314
|
816
|
+
qontract_reconcile-0.10.1rc832.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
817
|
+
qontract_reconcile-0.10.1rc832.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
|
818
|
+
qontract_reconcile-0.10.1rc832.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
819
|
+
qontract_reconcile-0.10.1rc832.dist-info/RECORD,,
|
reconcile/cli.py
CHANGED
@@ -2296,9 +2296,19 @@ def terraform_users(
|
|
2296
2296
|
@binary_version("terraform", ["version"], TERRAFORM_VERSION_REGEX, TERRAFORM_VERSION)
|
2297
2297
|
@enable_deletion(default=False)
|
2298
2298
|
@account_name
|
2299
|
+
@enable_extended_early_exit
|
2300
|
+
@extended_early_exit_cache_ttl_seconds
|
2301
|
+
@log_cached_log_output
|
2299
2302
|
@click.pass_context
|
2300
2303
|
def terraform_vpc_peerings(
|
2301
|
-
ctx,
|
2304
|
+
ctx,
|
2305
|
+
print_to_file,
|
2306
|
+
enable_deletion,
|
2307
|
+
thread_pool_size,
|
2308
|
+
account_name,
|
2309
|
+
enable_extended_early_exit,
|
2310
|
+
extended_early_exit_cache_ttl_seconds,
|
2311
|
+
log_cached_log_output,
|
2302
2312
|
):
|
2303
2313
|
import reconcile.terraform_vpc_peerings
|
2304
2314
|
|
@@ -2311,6 +2321,9 @@ def terraform_vpc_peerings(
|
|
2311
2321
|
enable_deletion,
|
2312
2322
|
thread_pool_size,
|
2313
2323
|
account_name,
|
2324
|
+
enable_extended_early_exit=enable_extended_early_exit,
|
2325
|
+
extended_early_exit_cache_ttl_seconds=extended_early_exit_cache_ttl_seconds,
|
2326
|
+
log_cached_log_output=log_cached_log_output,
|
2314
2327
|
)
|
2315
2328
|
|
2316
2329
|
|
@@ -1,10 +1,8 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
import sys
|
4
|
-
from
|
5
|
-
|
6
|
-
Optional,
|
7
|
-
)
|
4
|
+
from collections.abc import Callable, Iterable, Mapping
|
5
|
+
from typing import Any, TypedDict
|
8
6
|
|
9
7
|
import reconcile.utils.terraform_client as terraform
|
10
8
|
import reconcile.utils.terrascript_aws_client as terrascript
|
@@ -15,11 +13,16 @@ from reconcile.utils import (
|
|
15
13
|
)
|
16
14
|
from reconcile.utils.aws_api import AWSApi
|
17
15
|
from reconcile.utils.defer import defer
|
16
|
+
from reconcile.utils.extended_early_exit import (
|
17
|
+
ExtendedEarlyExitRunnerResult,
|
18
|
+
extended_early_exit_run,
|
19
|
+
)
|
18
20
|
from reconcile.utils.ocm import (
|
19
21
|
OCM,
|
20
22
|
OCMMap,
|
21
23
|
)
|
22
24
|
from reconcile.utils.semver_helper import make_semver
|
25
|
+
from reconcile.utils.unleash.client import get_feature_toggle_state
|
23
26
|
|
24
27
|
QONTRACT_INTEGRATION = "terraform_vpc_peerings"
|
25
28
|
QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
|
@@ -29,7 +32,11 @@ class BadTerraformPeeringState(Exception):
|
|
29
32
|
pass
|
30
33
|
|
31
34
|
|
32
|
-
def find_matching_peering(
|
35
|
+
def find_matching_peering(
|
36
|
+
from_cluster: Mapping[str, Any],
|
37
|
+
to_cluster: Mapping[str, Any],
|
38
|
+
desired_provider: str,
|
39
|
+
) -> Mapping[str, Any] | None:
|
33
40
|
"""
|
34
41
|
Ensures there is a matching peering with the desired provider type
|
35
42
|
going from the destination (to) cluster back to this one (from)
|
@@ -47,8 +54,8 @@ def find_matching_peering(from_cluster, to_cluster, desired_provider):
|
|
47
54
|
|
48
55
|
|
49
56
|
def _get_default_management_account(
|
50
|
-
cluster:
|
51
|
-
) ->
|
57
|
+
cluster: Mapping[str, Any],
|
58
|
+
) -> Mapping[str, Any] | None:
|
52
59
|
cluster_infra_accounts = cluster["awsInfrastructureManagementAccounts"]
|
53
60
|
for infra_account_def in cluster_infra_accounts or []:
|
54
61
|
if (
|
@@ -60,11 +67,11 @@ def _get_default_management_account(
|
|
60
67
|
|
61
68
|
|
62
69
|
def _build_infrastructure_assume_role(
|
63
|
-
account:
|
64
|
-
cluster:
|
65
|
-
ocm:
|
66
|
-
provided_assume_role:
|
67
|
-
) ->
|
70
|
+
account: Mapping[str, Any],
|
71
|
+
cluster: Mapping[str, Any],
|
72
|
+
ocm: OCM | None,
|
73
|
+
provided_assume_role: str | None,
|
74
|
+
) -> dict[str, Any] | None:
|
68
75
|
if provided_assume_role:
|
69
76
|
assume_role = provided_assume_role
|
70
77
|
elif cluster["spec"].get("account"):
|
@@ -97,11 +104,11 @@ def _build_infrastructure_assume_role(
|
|
97
104
|
|
98
105
|
|
99
106
|
def aws_assume_roles_for_cluster_vpc_peering(
|
100
|
-
requester_connection:
|
101
|
-
requester_cluster:
|
102
|
-
accepter_connection:
|
103
|
-
accepter_cluster:
|
104
|
-
ocm:
|
107
|
+
requester_connection: Mapping[str, Any],
|
108
|
+
requester_cluster: Mapping[str, Any],
|
109
|
+
accepter_connection: Mapping[str, Any],
|
110
|
+
accepter_cluster: Mapping[str, Any],
|
111
|
+
ocm: OCM | None,
|
105
112
|
) -> tuple[str, dict[str, Any], dict[str, Any]]:
|
106
113
|
# check if dedicated infra accounts have been declared on the
|
107
114
|
# accepters peering connection or on the accepters cluster
|
@@ -159,8 +166,11 @@ def aws_assume_roles_for_cluster_vpc_peering(
|
|
159
166
|
|
160
167
|
|
161
168
|
def build_desired_state_single_cluster(
|
162
|
-
cluster_info
|
163
|
-
|
169
|
+
cluster_info: Mapping[str, Any],
|
170
|
+
ocm: OCM | None,
|
171
|
+
awsapi: AWSApi,
|
172
|
+
account_filter: str | None,
|
173
|
+
) -> list[dict[str, Any]]:
|
164
174
|
cluster_name = cluster_info["name"]
|
165
175
|
|
166
176
|
peerings = []
|
@@ -268,8 +278,11 @@ def build_desired_state_single_cluster(
|
|
268
278
|
|
269
279
|
|
270
280
|
def build_desired_state_all_clusters(
|
271
|
-
clusters
|
272
|
-
|
281
|
+
clusters: Iterable[Mapping[str, Any]],
|
282
|
+
ocm_map: OCMMap | None,
|
283
|
+
awsapi: AWSApi,
|
284
|
+
account_filter: str | None,
|
285
|
+
) -> tuple[list[dict[str, Any]], bool]:
|
273
286
|
"""
|
274
287
|
Fetch state for VPC peerings between two OCM clusters
|
275
288
|
"""
|
@@ -292,8 +305,11 @@ def build_desired_state_all_clusters(
|
|
292
305
|
|
293
306
|
|
294
307
|
def build_desired_state_vpc_mesh_single_cluster(
|
295
|
-
cluster_info
|
296
|
-
|
308
|
+
cluster_info: Mapping[str, Any],
|
309
|
+
ocm: OCM | None,
|
310
|
+
awsapi: AWSApi,
|
311
|
+
account_filter: str | None,
|
312
|
+
) -> list[dict[str, Any]]:
|
297
313
|
desired_state = []
|
298
314
|
|
299
315
|
cluster = cluster_info["name"]
|
@@ -386,8 +402,11 @@ def build_desired_state_vpc_mesh_single_cluster(
|
|
386
402
|
|
387
403
|
|
388
404
|
def build_desired_state_vpc_mesh(
|
389
|
-
clusters
|
390
|
-
|
405
|
+
clusters: Iterable[Mapping[str, Any]],
|
406
|
+
ocm_map: OCMMap | None,
|
407
|
+
awsapi: AWSApi,
|
408
|
+
account_filter: str | None,
|
409
|
+
) -> tuple[list[dict[str, Any]], bool]:
|
391
410
|
"""
|
392
411
|
Fetch state for VPC peerings between a cluster and all VPCs in an account
|
393
412
|
"""
|
@@ -410,8 +429,11 @@ def build_desired_state_vpc_mesh(
|
|
410
429
|
|
411
430
|
|
412
431
|
def build_desired_state_vpc_single_cluster(
|
413
|
-
cluster_info
|
414
|
-
|
432
|
+
cluster_info: Mapping[str, Any],
|
433
|
+
ocm: OCM | None,
|
434
|
+
awsapi: AWSApi,
|
435
|
+
account_filter: str | None,
|
436
|
+
) -> list[dict[str, Any]]:
|
415
437
|
desired_state = []
|
416
438
|
|
417
439
|
peering_info = cluster_info["peering"]
|
@@ -506,15 +528,18 @@ def build_desired_state_vpc_single_cluster(
|
|
506
528
|
return desired_state
|
507
529
|
|
508
530
|
|
509
|
-
def _private_hosted_control_plane(cluster_info:
|
531
|
+
def _private_hosted_control_plane(cluster_info: Mapping[str, Any]) -> bool:
|
510
532
|
return bool(
|
511
533
|
cluster_info["spec"].get("hypershift") and cluster_info["spec"].get("private")
|
512
534
|
)
|
513
535
|
|
514
536
|
|
515
537
|
def build_desired_state_vpc(
|
516
|
-
clusters
|
517
|
-
|
538
|
+
clusters: Iterable[Mapping[str, Any]],
|
539
|
+
ocm_map: OCMMap | None,
|
540
|
+
awsapi: AWSApi,
|
541
|
+
account_filter: str | None,
|
542
|
+
) -> tuple[list[dict[str, Any]], bool]:
|
518
543
|
"""
|
519
544
|
Fetch state for VPC peerings between a cluster and a VPC (account)
|
520
545
|
"""
|
@@ -538,13 +563,16 @@ def build_desired_state_vpc(
|
|
538
563
|
|
539
564
|
@defer
|
540
565
|
def run(
|
541
|
-
dry_run,
|
542
|
-
print_to_file=None,
|
543
|
-
enable_deletion=False,
|
544
|
-
thread_pool_size=10,
|
545
|
-
account_name:
|
546
|
-
|
547
|
-
|
566
|
+
dry_run: bool,
|
567
|
+
print_to_file: bool | None = None,
|
568
|
+
enable_deletion: bool = False,
|
569
|
+
thread_pool_size: int = 10,
|
570
|
+
account_name: str | None = None,
|
571
|
+
enable_extended_early_exit: bool = False,
|
572
|
+
extended_early_exit_cache_ttl_seconds: int = 3600,
|
573
|
+
log_cached_log_output: bool = False,
|
574
|
+
defer: Callable | None = None,
|
575
|
+
) -> None:
|
548
576
|
settings = queries.get_secret_reader_settings()
|
549
577
|
clusters = queries.get_clusters_with_peering_settings()
|
550
578
|
with_ocm = any(c.get("ocm") for c in clusters)
|
@@ -638,10 +666,14 @@ def run(
|
|
638
666
|
ts.populate_additional_providers(infra_account_name, items)
|
639
667
|
ts.populate_vpc_peerings(desired_state)
|
640
668
|
working_dirs = ts.dump(print_to_file=print_to_file)
|
669
|
+
terraform_configurations = ts.terraform_configurations()
|
641
670
|
|
642
671
|
if print_to_file:
|
643
672
|
sys.exit(0 if dry_run else int(any(errors)))
|
644
673
|
|
674
|
+
if any(errors):
|
675
|
+
sys.exit(1)
|
676
|
+
|
645
677
|
tf = terraform.TerraformClient(
|
646
678
|
QONTRACT_INTEGRATION,
|
647
679
|
QONTRACT_INTEGRATION_VERSION,
|
@@ -651,34 +683,68 @@ def run(
|
|
651
683
|
thread_pool_size,
|
652
684
|
awsapi,
|
653
685
|
)
|
686
|
+
if defer:
|
687
|
+
defer(tf.cleanup)
|
654
688
|
|
655
|
-
|
656
|
-
|
689
|
+
runner_params: RunnerParams = dict(
|
690
|
+
tf=tf,
|
691
|
+
dry_run=dry_run,
|
692
|
+
enable_deletion=enable_deletion,
|
693
|
+
)
|
694
|
+
|
695
|
+
if enable_extended_early_exit and get_feature_toggle_state(
|
696
|
+
"terraform-vpc-peerings-extended-early-exit",
|
697
|
+
default=True,
|
698
|
+
):
|
699
|
+
cache_source = CacheSource(terraform_configurations=terraform_configurations)
|
700
|
+
extended_early_exit_run(
|
701
|
+
integration=QONTRACT_INTEGRATION,
|
702
|
+
integration_version=QONTRACT_INTEGRATION_VERSION,
|
703
|
+
dry_run=dry_run,
|
704
|
+
cache_source=cache_source,
|
705
|
+
shard=account_name if account_name else "",
|
706
|
+
ttl_seconds=extended_early_exit_cache_ttl_seconds,
|
707
|
+
logger=logging.getLogger(),
|
708
|
+
runner=runner,
|
709
|
+
runner_params=runner_params,
|
710
|
+
log_cached_log_output=log_cached_log_output,
|
711
|
+
)
|
712
|
+
else:
|
713
|
+
runner(**runner_params)
|
714
|
+
|
715
|
+
|
716
|
+
class CacheSource(TypedDict):
|
717
|
+
terraform_configurations: dict[str, str]
|
718
|
+
|
719
|
+
|
720
|
+
class RunnerParams(TypedDict):
|
721
|
+
tf: terraform.TerraformClient
|
722
|
+
dry_run: bool
|
723
|
+
enable_deletion: bool
|
657
724
|
|
658
|
-
defer(tf.cleanup)
|
659
725
|
|
726
|
+
def runner(
|
727
|
+
dry_run: bool,
|
728
|
+
tf: terraform.TerraformClient,
|
729
|
+
enable_deletion: bool = False,
|
730
|
+
) -> ExtendedEarlyExitRunnerResult:
|
660
731
|
disabled_deletions_detected, err = tf.plan(enable_deletion)
|
661
|
-
errors.append(err)
|
662
732
|
if disabled_deletions_detected:
|
663
|
-
|
664
|
-
|
733
|
+
raise RuntimeError("Terraform plan has disabled deletions detected")
|
734
|
+
if err:
|
735
|
+
raise RuntimeError("Terraform plan has errors")
|
665
736
|
|
666
737
|
if dry_run:
|
667
|
-
|
668
|
-
|
669
|
-
|
738
|
+
return ExtendedEarlyExitRunnerResult(payload={}, applied_count=0)
|
739
|
+
|
740
|
+
if err := tf.apply():
|
741
|
+
raise RuntimeError("Terraform apply has errors")
|
670
742
|
|
671
|
-
|
672
|
-
sys.exit(int(any(errors)))
|
743
|
+
return ExtendedEarlyExitRunnerResult(payload={}, applied_count=tf.apply_count)
|
673
744
|
|
674
745
|
|
675
|
-
def early_exit_desired_state(
|
676
|
-
|
677
|
-
enable_deletion=False,
|
678
|
-
thread_pool_size=10,
|
679
|
-
account_name: Optional[str] = None,
|
680
|
-
) -> dict[str, Any]:
|
681
|
-
if account_name:
|
746
|
+
def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
747
|
+
if kwargs.get("account_name"):
|
682
748
|
raise ValueError(
|
683
749
|
"terraform-vpc-peerings early-exit check does not support sharding yet"
|
684
750
|
)
|
@@ -1,11 +1,9 @@
|
|
1
1
|
import sys
|
2
|
-
from typing import
|
3
|
-
Any,
|
4
|
-
Optional,
|
5
|
-
)
|
2
|
+
from typing import Any, Self
|
6
3
|
|
7
4
|
import pytest
|
8
5
|
import testslide
|
6
|
+
from pytest_mock import MockerFixture
|
9
7
|
|
10
8
|
import reconcile.terraform_vpc_peerings as integ
|
11
9
|
import reconcile.utils.terraform_client as terraform
|
@@ -23,8 +21,8 @@ class MockOCM:
|
|
23
21
|
self.assumes: dict[str, str] = {}
|
24
22
|
|
25
23
|
def register(
|
26
|
-
self, cluster: str, tf_account_id: str, tf_user: str, assume_role:
|
27
|
-
) ->
|
24
|
+
self, cluster: str, tf_account_id: str, tf_user: str, assume_role: str | None
|
25
|
+
) -> Self:
|
28
26
|
if not assume_role:
|
29
27
|
assume_role = f"arn::::{cluster}"
|
30
28
|
if not assume_role.startswith("arn:"):
|
@@ -33,11 +31,11 @@ class MockOCM:
|
|
33
31
|
return self
|
34
32
|
|
35
33
|
def get_aws_infrastructure_access_terraform_assume_role(
|
36
|
-
self, cluster, tf_account_id, tf_user
|
37
|
-
):
|
34
|
+
self, cluster: str, tf_account_id: str, tf_user: str
|
35
|
+
) -> str | None:
|
38
36
|
return self.assumes.get(f"{cluster}/{tf_account_id}/{tf_user}")
|
39
37
|
|
40
|
-
def auto_speced_mock(self, mocker) -> ocm.OCM:
|
38
|
+
def auto_speced_mock(self, mocker: MockerFixture) -> ocm.OCM:
|
41
39
|
ocm_mock = mocker.patch("reconcile.utils.ocm.OCM", autospec=True).return_value
|
42
40
|
ocm_mock.get_aws_infrastructure_access_terraform_assume_role.mock_add_spec(
|
43
41
|
ocm.OCM.get_aws_infrastructure_access_terraform_assume_role
|
@@ -50,15 +48,15 @@ class MockOCM:
|
|
50
48
|
|
51
49
|
class MockAWSAPI:
|
52
50
|
def __init__(self) -> None:
|
53
|
-
self.vpc_details: dict[str, tuple[str, list[str],
|
51
|
+
self.vpc_details: dict[str, tuple[str, list[str], str | None]] = {}
|
54
52
|
|
55
53
|
def register(
|
56
54
|
self,
|
57
55
|
vpc: str,
|
58
56
|
vpc_id: str,
|
59
57
|
route_tables: list[str],
|
60
|
-
vpce_sg:
|
61
|
-
) ->
|
58
|
+
vpce_sg: str | None = None,
|
59
|
+
) -> Self:
|
62
60
|
self.vpc_details[vpc] = (
|
63
61
|
vpc_id,
|
64
62
|
route_tables,
|
@@ -69,9 +67,9 @@ class MockAWSAPI:
|
|
69
67
|
def get_cluster_vpc_details(
|
70
68
|
self,
|
71
69
|
account: dict[str, Any],
|
72
|
-
route_tables=False,
|
73
|
-
subnets=False,
|
74
|
-
hcp_vpc_endpoint_sg=False,
|
70
|
+
route_tables: bool = False,
|
71
|
+
subnets: bool = False,
|
72
|
+
hcp_vpc_endpoint_sg: bool = False,
|
75
73
|
) -> tuple:
|
76
74
|
if account["assume_cidr"] in self.vpc_details:
|
77
75
|
vpc_id, rt, sg_id = self.vpc_details[account["assume_cidr"]]
|
@@ -80,7 +78,7 @@ class MockAWSAPI:
|
|
80
78
|
return vpc_id, rt, None, sg_id if hcp_vpc_endpoint_sg else None
|
81
79
|
return None, None, None, None
|
82
80
|
|
83
|
-
def auto_speced_mock(self, mocker) -> aws_api.AWSApi:
|
81
|
+
def auto_speced_mock(self, mocker: MockerFixture) -> aws_api.AWSApi:
|
84
82
|
aws_api_mock = mocker.patch(
|
85
83
|
"reconcile.utils.aws_api.AWSApi", autospec=True
|
86
84
|
).return_value
|
@@ -93,14 +91,14 @@ class MockAWSAPI:
|
|
93
91
|
|
94
92
|
def build_cluster(
|
95
93
|
name: str,
|
96
|
-
vpc:
|
97
|
-
read_only_accounts:
|
98
|
-
network_mgmt_accounts:
|
99
|
-
peering_connections:
|
94
|
+
vpc: str | None = None,
|
95
|
+
read_only_accounts: list[str] | None = None,
|
96
|
+
network_mgmt_accounts: list[str] | None = None,
|
97
|
+
peering_connections: list[dict[str, Any]] | None = None,
|
100
98
|
hcp: bool = False,
|
101
99
|
private: bool = False,
|
102
|
-
sg:
|
103
|
-
):
|
100
|
+
sg: str | None = None,
|
101
|
+
) -> dict[str, Any]:
|
104
102
|
if not vpc:
|
105
103
|
vpc = name
|
106
104
|
cluster = {
|
@@ -150,7 +148,7 @@ def build_cluster(
|
|
150
148
|
|
151
149
|
def build_requester_connection(
|
152
150
|
name: str, peer_cluster: dict[str, Any], manage_routes: bool = True
|
153
|
-
):
|
151
|
+
) -> dict[str, Any]:
|
154
152
|
return {
|
155
153
|
"name": name,
|
156
154
|
"provider": "cluster-vpc-requester",
|
@@ -162,9 +160,9 @@ def build_requester_connection(
|
|
162
160
|
def build_accepter_connection(
|
163
161
|
name: str,
|
164
162
|
cluster: str,
|
165
|
-
aws_infra_acc:
|
163
|
+
aws_infra_acc: str | None = None,
|
166
164
|
manage_routes: bool = True,
|
167
|
-
):
|
165
|
+
) -> dict[str, Any]:
|
168
166
|
connection = {
|
169
167
|
"name": name,
|
170
168
|
"provider": "cluster-vpc-accepter",
|
@@ -182,7 +180,7 @@ def build_accepter_connection(
|
|
182
180
|
return connection
|
183
181
|
|
184
182
|
|
185
|
-
def test_c2c_vpc_peering_assume_role_accepter_connection_acc_overwrite(
|
183
|
+
def test_c2c_vpc_peering_assume_role_accepter_connection_acc_overwrite() -> None:
|
186
184
|
"""
|
187
185
|
makes sure the peer connection account overwrite on the accepter is used
|
188
186
|
when available. in this test, the overwrite is also allowed
|
@@ -210,7 +208,7 @@ def test_c2c_vpc_peering_assume_role_accepter_connection_acc_overwrite(mocker):
|
|
210
208
|
requester_cluster,
|
211
209
|
accepter_connection,
|
212
210
|
accepter_cluster,
|
213
|
-
ocm,
|
211
|
+
ocm, # type: ignore
|
214
212
|
)
|
215
213
|
|
216
214
|
assert infra_acc_name == "acc_overwrite"
|
@@ -238,7 +236,7 @@ def test_c2c_vpc_peering_assume_role_accepter_connection_acc_overwrite(mocker):
|
|
238
236
|
assert acc_aws == expected_acc_aws
|
239
237
|
|
240
238
|
|
241
|
-
def test_c2c_vpc_peering_assume_role_acc_overwrite_fail(
|
239
|
+
def test_c2c_vpc_peering_assume_role_acc_overwrite_fail() -> None:
|
242
240
|
"""
|
243
241
|
try overwrite the account to be used on the accepter connection with an
|
244
242
|
account not listed on the accepter cluster
|
@@ -263,12 +261,12 @@ def test_c2c_vpc_peering_assume_role_acc_overwrite_fail(mocker):
|
|
263
261
|
requester_cluster,
|
264
262
|
accepter_connection,
|
265
263
|
accepter_cluster,
|
266
|
-
ocm,
|
264
|
+
ocm, # type: ignore
|
267
265
|
)
|
268
266
|
assert str(ex.value).startswith("[account_not_allowed]")
|
269
267
|
|
270
268
|
|
271
|
-
def test_c2c_vpc_peering_assume_role_accepter_cluster_account(
|
269
|
+
def test_c2c_vpc_peering_assume_role_accepter_cluster_account() -> None:
|
272
270
|
"""
|
273
271
|
makes sure the clusters default infra account is used when no peer
|
274
272
|
connection overwrite exists
|
@@ -292,7 +290,7 @@ def test_c2c_vpc_peering_assume_role_accepter_cluster_account(mocker):
|
|
292
290
|
requester_cluster,
|
293
291
|
accepter_connection,
|
294
292
|
accepter_cluster,
|
295
|
-
ocm,
|
293
|
+
ocm, # type: ignore
|
296
294
|
)
|
297
295
|
|
298
296
|
assert infra_acc_name == "default_acc"
|
@@ -320,7 +318,7 @@ def test_c2c_vpc_peering_assume_role_accepter_cluster_account(mocker):
|
|
320
318
|
assert acc_aws == expected_acc_aws
|
321
319
|
|
322
320
|
|
323
|
-
def test_c2c_vpc_peering_missing_ocm_assume_role(
|
321
|
+
def test_c2c_vpc_peering_missing_ocm_assume_role() -> None:
|
324
322
|
"""
|
325
323
|
makes sure the clusters infra account is used when no peer connection
|
326
324
|
overwrite exists
|
@@ -338,12 +336,12 @@ def test_c2c_vpc_peering_missing_ocm_assume_role(mocker):
|
|
338
336
|
requester_cluster,
|
339
337
|
accepter_connection,
|
340
338
|
accepter_cluster,
|
341
|
-
ocm,
|
339
|
+
ocm, # type: ignore
|
342
340
|
)
|
343
341
|
assert str(ex.value).startswith("[assume_role_not_found]")
|
344
342
|
|
345
343
|
|
346
|
-
def test_c2c_vpc_peering_missing_account(
|
344
|
+
def test_c2c_vpc_peering_missing_account() -> None:
|
347
345
|
"""
|
348
346
|
test the fallback logic, looking for network-mgmt groups accounts
|
349
347
|
"""
|
@@ -360,12 +358,12 @@ def test_c2c_vpc_peering_missing_account(mocker):
|
|
360
358
|
requester_cluster,
|
361
359
|
accepter_connection,
|
362
360
|
accepter_cluster,
|
363
|
-
ocm,
|
361
|
+
ocm, # type: ignore
|
364
362
|
)
|
365
363
|
assert str(ex.value).startswith("[no_account_available]")
|
366
364
|
|
367
365
|
|
368
|
-
def test_empty_run(mocker):
|
366
|
+
def test_empty_run(mocker: MockerFixture) -> None:
|
369
367
|
mocked_queries = mocker.patch("reconcile.terraform_vpc_peerings.queries")
|
370
368
|
mocked_queries.get_secret_reader_settings.return_value = {}
|
371
369
|
mocked_queries.get_clusters_with_peering_settings.return_value = []
|
@@ -390,7 +388,7 @@ def test_empty_run(mocker):
|
|
390
388
|
|
391
389
|
|
392
390
|
class TestRun(testslide.TestCase):
|
393
|
-
def setUp(self):
|
391
|
+
def setUp(self) -> None:
|
394
392
|
super().setUp()
|
395
393
|
|
396
394
|
self.awsapi = testslide.StrictMock(aws_api.AWSApi)
|
@@ -412,6 +410,7 @@ class TestRun(testslide.TestCase):
|
|
412
410
|
self.mock_constructor(terraform, "TerraformClient").to_return_value(
|
413
411
|
self.terraform
|
414
412
|
)
|
413
|
+
self.terraform.apply_count = 1
|
415
414
|
self.mock_constructor(terrascript, "TerrascriptClient").to_return_value(
|
416
415
|
self.terrascript
|
417
416
|
)
|
@@ -442,11 +441,14 @@ class TestRun(testslide.TestCase):
|
|
442
441
|
self.mock_callable(self.terrascript, "dump").to_return_value({
|
443
442
|
"some_account": "/some/dir"
|
444
443
|
}).and_assert_called_once()
|
444
|
+
self.mock_callable(
|
445
|
+
self.terrascript, "terraform_configurations"
|
446
|
+
).to_return_value({"foo": "bar"}).and_assert_called_once()
|
445
447
|
# Sigh...
|
446
448
|
self.exit = self.mock_callable(sys, "exit").to_raise(OSError("Exit called!"))
|
447
449
|
self.addCleanup(testslide.mock_callable.unpatch_all_callable_mocks)
|
448
450
|
|
449
|
-
def initialize_desired_states(self, error_code):
|
451
|
+
def initialize_desired_states(self, error_code: bool) -> None:
|
450
452
|
self.build_desired_state_vpc.to_return_value((
|
451
453
|
[
|
452
454
|
{
|
@@ -499,7 +501,7 @@ class TestRun(testslide.TestCase):
|
|
499
501
|
],
|
500
502
|
).to_return_value(None).and_assert_called_once()
|
501
503
|
|
502
|
-
def test_all_fine(self):
|
504
|
+
def test_all_fine(self) -> None:
|
503
505
|
self.initialize_desired_states(False)
|
504
506
|
self.mock_callable(self.terraform, "plan").to_return_value((
|
505
507
|
False,
|
@@ -511,11 +513,9 @@ class TestRun(testslide.TestCase):
|
|
511
513
|
self.mock_callable(self.terraform, "apply").to_return_value(
|
512
514
|
None
|
513
515
|
).and_assert_called_once()
|
514
|
-
|
515
|
-
with self.assertRaises(OSError):
|
516
|
-
integ.run(False, print_to_file=None, enable_deletion=False)
|
516
|
+
integ.run(False, print_to_file=None, enable_deletion=False)
|
517
517
|
|
518
|
-
def test_fail_state(self):
|
518
|
+
def test_fail_state(self) -> None:
|
519
519
|
"""Ensure we don't change the world if there are failures"""
|
520
520
|
self.initialize_desired_states(True)
|
521
521
|
self.mock_callable(self.terraform, "plan").to_return_value((
|
@@ -532,7 +532,7 @@ class TestRun(testslide.TestCase):
|
|
532
532
|
with self.assertRaises(OSError):
|
533
533
|
integ.run(False, print_to_file=None, enable_deletion=True)
|
534
534
|
|
535
|
-
def test_dry_run(self):
|
535
|
+
def test_dry_run(self) -> None:
|
536
536
|
self.initialize_desired_states(False)
|
537
537
|
|
538
538
|
self.mock_callable(self.terraform, "plan").to_return_value((
|
@@ -545,11 +545,9 @@ class TestRun(testslide.TestCase):
|
|
545
545
|
self.mock_callable(self.terraform, "apply").to_return_value(
|
546
546
|
None
|
547
547
|
).and_assert_not_called()
|
548
|
-
|
549
|
-
with self.assertRaises(OSError):
|
550
|
-
integ.run(True, print_to_file=None, enable_deletion=False)
|
548
|
+
integ.run(True, print_to_file=None, enable_deletion=False)
|
551
549
|
|
552
|
-
def test_dry_run_with_failures(self):
|
550
|
+
def test_dry_run_with_failures(self) -> None:
|
553
551
|
"""This is what we do during PR checks and new clusters!"""
|
554
552
|
self.initialize_desired_states(True)
|
555
553
|
self.mock_callable(self.terraform, "plan").to_return_value((
|
@@ -563,7 +561,7 @@ class TestRun(testslide.TestCase):
|
|
563
561
|
with self.assertRaises(OSError):
|
564
562
|
integ.run(True, print_to_file=None, enable_deletion=False)
|
565
563
|
|
566
|
-
def test_dry_run_print_only_with_failures(self):
|
564
|
+
def test_dry_run_print_only_with_failures(self) -> None:
|
567
565
|
"""This is what we do during PR checks and new clusters!"""
|
568
566
|
self.initialize_desired_states(True)
|
569
567
|
self.mock_callable(self.terraform, "plan").to_return_value((
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import pytest
|
2
2
|
import testslide
|
3
|
+
from pytest_mock import MockerFixture
|
3
4
|
|
4
5
|
import reconcile.terraform_vpc_peerings as sut
|
5
6
|
from reconcile.test.test_terraform_vpc_peerings import (
|
@@ -15,7 +16,7 @@ from reconcile.utils import (
|
|
15
16
|
)
|
16
17
|
|
17
18
|
|
18
|
-
def test_c2c_all_clusters(
|
19
|
+
def test_c2c_all_clusters() -> None:
|
19
20
|
"""
|
20
21
|
happy path
|
21
22
|
"""
|
@@ -101,27 +102,36 @@ def test_c2c_all_clusters(mocker):
|
|
101
102
|
|
102
103
|
# no account filter
|
103
104
|
result, error = sut.build_desired_state_all_clusters(
|
104
|
-
[requester_cluster],
|
105
|
+
[requester_cluster],
|
106
|
+
ocm_map, # type: ignore
|
107
|
+
awsapi, # type: ignore
|
108
|
+
account_filter=None,
|
105
109
|
)
|
106
110
|
assert result == expected
|
107
111
|
assert not error
|
108
112
|
|
109
113
|
# correct account filter
|
110
114
|
result, error = sut.build_desired_state_all_clusters(
|
111
|
-
[requester_cluster],
|
115
|
+
[requester_cluster],
|
116
|
+
ocm_map, # type: ignore
|
117
|
+
awsapi, # type: ignore
|
118
|
+
account_filter="acc",
|
112
119
|
)
|
113
120
|
assert result == expected
|
114
121
|
assert not error
|
115
122
|
|
116
123
|
# wrong account filter
|
117
124
|
result, error = sut.build_desired_state_all_clusters(
|
118
|
-
[requester_cluster],
|
125
|
+
[requester_cluster],
|
126
|
+
ocm_map, # type: ignore
|
127
|
+
awsapi, # type: ignore
|
128
|
+
account_filter="another_account",
|
119
129
|
)
|
120
130
|
assert not result
|
121
131
|
assert not error
|
122
132
|
|
123
133
|
|
124
|
-
def test_c2c_one_cluster_failing_recoverable(mocker):
|
134
|
+
def test_c2c_one_cluster_failing_recoverable(mocker: MockerFixture) -> None:
|
125
135
|
"""
|
126
136
|
in this scenario, the handling of a single cluster fails with known
|
127
137
|
exceptions
|
@@ -134,14 +144,17 @@ def test_c2c_one_cluster_failing_recoverable(mocker):
|
|
134
144
|
)
|
135
145
|
|
136
146
|
result, error = sut.build_desired_state_all_clusters(
|
137
|
-
[{"name": "cluster"}],
|
147
|
+
[{"name": "cluster"}],
|
148
|
+
None,
|
149
|
+
None, # type: ignore
|
150
|
+
account_filter=None,
|
138
151
|
)
|
139
152
|
|
140
153
|
assert not result
|
141
154
|
assert error
|
142
155
|
|
143
156
|
|
144
|
-
def test_c2c_one_cluster_failing_weird(mocker):
|
157
|
+
def test_c2c_one_cluster_failing_weird(mocker: MockerFixture) -> None:
|
145
158
|
"""
|
146
159
|
in this scenario, the handling of a single cluster fails with unexpected
|
147
160
|
exceptions
|
@@ -154,7 +167,10 @@ def test_c2c_one_cluster_failing_weird(mocker):
|
|
154
167
|
|
155
168
|
with pytest.raises(ValueError) as ex:
|
156
169
|
sut.build_desired_state_all_clusters(
|
157
|
-
[{"name": "cluster"}],
|
170
|
+
[{"name": "cluster"}],
|
171
|
+
None,
|
172
|
+
None, # type: ignore
|
173
|
+
account_filter=None,
|
158
174
|
)
|
159
175
|
|
160
176
|
assert str(ex.value) == SOMETHING_UNEXPECTED
|
@@ -173,14 +189,13 @@ def test_c2c_one_cluster_failing_weird(mocker):
|
|
173
189
|
],
|
174
190
|
)
|
175
191
|
def test_c2c_hcp(
|
176
|
-
accepter_hcp,
|
177
|
-
accepter_private,
|
178
|
-
requester_hcp,
|
179
|
-
requester_private,
|
180
|
-
expected_accepter_security_group,
|
181
|
-
expected_requester_security_group,
|
182
|
-
|
183
|
-
):
|
192
|
+
accepter_hcp: bool,
|
193
|
+
accepter_private: bool,
|
194
|
+
requester_hcp: bool,
|
195
|
+
requester_private: bool,
|
196
|
+
expected_accepter_security_group: str | None,
|
197
|
+
expected_requester_security_group: str | None,
|
198
|
+
) -> None:
|
184
199
|
accepter_cluster = build_cluster(
|
185
200
|
name="accepter_cluster",
|
186
201
|
vpc="accepter_vpc",
|
@@ -267,24 +282,33 @@ def test_c2c_hcp(
|
|
267
282
|
|
268
283
|
# no account filtering
|
269
284
|
result = sut.build_desired_state_single_cluster(
|
270
|
-
requester_cluster,
|
285
|
+
requester_cluster,
|
286
|
+
ocm, # type: ignore
|
287
|
+
awsapi, # type: ignore
|
288
|
+
account_filter=None,
|
271
289
|
)
|
272
290
|
assert result == expected
|
273
291
|
|
274
292
|
# correct account filtering
|
275
293
|
result = sut.build_desired_state_single_cluster(
|
276
|
-
requester_cluster,
|
294
|
+
requester_cluster,
|
295
|
+
ocm, # type: ignore
|
296
|
+
awsapi, # type: ignore
|
297
|
+
account_filter="acc",
|
277
298
|
)
|
278
299
|
assert result == expected
|
279
300
|
|
280
301
|
# correct account filtering
|
281
302
|
result = sut.build_desired_state_single_cluster(
|
282
|
-
requester_cluster,
|
303
|
+
requester_cluster,
|
304
|
+
ocm, # type: ignore
|
305
|
+
awsapi, # type: ignore
|
306
|
+
account_filter="another_account",
|
283
307
|
)
|
284
308
|
assert not result
|
285
309
|
|
286
310
|
|
287
|
-
def test_c2c_base(
|
311
|
+
def test_c2c_base() -> None:
|
288
312
|
"""
|
289
313
|
happy path
|
290
314
|
"""
|
@@ -368,24 +392,33 @@ def test_c2c_base(mocker):
|
|
368
392
|
|
369
393
|
# no account filtering
|
370
394
|
result = sut.build_desired_state_single_cluster(
|
371
|
-
requester_cluster,
|
395
|
+
requester_cluster,
|
396
|
+
ocm, # type: ignore
|
397
|
+
awsapi, # type: ignore
|
398
|
+
account_filter=None,
|
372
399
|
)
|
373
400
|
assert result == expected
|
374
401
|
|
375
402
|
# correct account filtering
|
376
403
|
result = sut.build_desired_state_single_cluster(
|
377
|
-
requester_cluster,
|
404
|
+
requester_cluster,
|
405
|
+
ocm, # type: ignore
|
406
|
+
awsapi, # type: ignore
|
407
|
+
account_filter="acc",
|
378
408
|
)
|
379
409
|
assert result == expected
|
380
410
|
|
381
411
|
# correct account filtering
|
382
412
|
result = sut.build_desired_state_single_cluster(
|
383
|
-
requester_cluster,
|
413
|
+
requester_cluster,
|
414
|
+
ocm, # type: ignore
|
415
|
+
awsapi, # type: ignore
|
416
|
+
account_filter="another_account",
|
384
417
|
)
|
385
418
|
assert not result
|
386
419
|
|
387
420
|
|
388
|
-
def test_c2c_no_peerings(
|
421
|
+
def test_c2c_no_peerings() -> None:
|
389
422
|
"""
|
390
423
|
in this scenario, the requester cluster has no peerings defines,
|
391
424
|
which results in an empty desired state
|
@@ -398,14 +431,14 @@ def test_c2c_no_peerings(mocker):
|
|
398
431
|
)
|
399
432
|
result = sut.build_desired_state_single_cluster(
|
400
433
|
requester_cluster,
|
401
|
-
MockOCM(),
|
402
|
-
MockAWSAPI(),
|
434
|
+
MockOCM(), # type: ignore
|
435
|
+
MockAWSAPI(), # type: ignore
|
403
436
|
account_filter=None,
|
404
437
|
)
|
405
438
|
assert not result
|
406
439
|
|
407
440
|
|
408
|
-
def test_c2c_no_matches(
|
441
|
+
def test_c2c_no_matches() -> None:
|
409
442
|
"""
|
410
443
|
in this scenario, the accepter cluster has no cluster-vpc-accepter
|
411
444
|
connection that references back to the requester cluster
|
@@ -430,14 +463,14 @@ def test_c2c_no_matches(mocker):
|
|
430
463
|
with pytest.raises(sut.BadTerraformPeeringState) as ex:
|
431
464
|
sut.build_desired_state_single_cluster(
|
432
465
|
requester_cluster,
|
433
|
-
MockOCM(),
|
434
|
-
MockAWSAPI(),
|
466
|
+
MockOCM(), # type: ignore
|
467
|
+
MockAWSAPI(), # type: ignore
|
435
468
|
account_filter=None,
|
436
469
|
)
|
437
470
|
assert str(ex.value).startswith("[no_matching_peering]")
|
438
471
|
|
439
472
|
|
440
|
-
def test_c2c_no_vpc_in_aws(
|
473
|
+
def test_c2c_no_vpc_in_aws() -> None:
|
441
474
|
"""
|
442
475
|
in this scenario, there are no VPCs found in AWS
|
443
476
|
"""
|
@@ -467,12 +500,15 @@ def test_c2c_no_vpc_in_aws(mocker):
|
|
467
500
|
awsapi = MockAWSAPI()
|
468
501
|
|
469
502
|
desired_state = sut.build_desired_state_single_cluster(
|
470
|
-
requester_cluster,
|
503
|
+
requester_cluster,
|
504
|
+
ocm, # type: ignore
|
505
|
+
awsapi, # type: ignore
|
506
|
+
account_filter=None,
|
471
507
|
)
|
472
508
|
assert desired_state == []
|
473
509
|
|
474
510
|
|
475
|
-
def test_c2c_no_peer_account(
|
511
|
+
def test_c2c_no_peer_account() -> None:
|
476
512
|
"""
|
477
513
|
in this scenario, the accepters connection and the accepters cluster
|
478
514
|
have no aws infrastructura account available to set up the peering″
|
@@ -503,13 +539,16 @@ def test_c2c_no_peer_account(mocker):
|
|
503
539
|
|
504
540
|
with pytest.raises(sut.BadTerraformPeeringState) as ex:
|
505
541
|
sut.build_desired_state_single_cluster(
|
506
|
-
requester_cluster,
|
542
|
+
requester_cluster,
|
543
|
+
ocm, # type: ignore
|
544
|
+
awsapi, # type: ignore
|
545
|
+
account_filter=None,
|
507
546
|
)
|
508
547
|
assert str(ex.value).startswith("[no_account_available]")
|
509
548
|
|
510
549
|
|
511
550
|
class TestBuildDesiredStateVpcMesh(testslide.TestCase):
|
512
|
-
def setUp(self):
|
551
|
+
def setUp(self) -> None:
|
513
552
|
super().setUp()
|
514
553
|
self.clusters = [
|
515
554
|
{
|
@@ -577,8 +616,8 @@ class TestBuildDesiredStateVpcMesh(testslide.TestCase):
|
|
577
616
|
"assume_region": "mars-hellas-1",
|
578
617
|
"assume_cidr": "172.25.0.0/12",
|
579
618
|
}
|
580
|
-
self.clusters[0]["peering"]["connections"][0]["cluster"] = self.peer_cluster
|
581
|
-
self.clusters[0]["peering"]["connections"][0]["account"] = self.peer_account
|
619
|
+
self.clusters[0]["peering"]["connections"][0]["cluster"] = self.peer_cluster # type: ignore
|
620
|
+
self.clusters[0]["peering"]["connections"][0]["account"] = self.peer_account # type: ignore
|
582
621
|
self.peer_vpc = {
|
583
622
|
"cidr_block": "172.30.0.0/12",
|
584
623
|
"vpc_id": "peervpcid",
|
@@ -589,11 +628,11 @@ class TestBuildDesiredStateVpcMesh(testslide.TestCase):
|
|
589
628
|
)
|
590
629
|
self.maxDiff = None
|
591
630
|
self.ocm = testslide.StrictMock(ocm.OCM)
|
592
|
-
self.ocm_map = {"clustername": self.ocm}
|
631
|
+
self.ocm_map: ocm.OCMMap = {"clustername": self.ocm} # type: ignore
|
593
632
|
self.ocm.get_aws_infrastructure_access_terraform_assume_role = (
|
594
633
|
lambda cluster, uid, tfuser: self.peer_account["assume_role"]
|
595
634
|
)
|
596
|
-
self.awsapi = testslide.StrictMock(aws_api.AWSApi)
|
635
|
+
self.awsapi: aws_api.AWSApi = testslide.StrictMock(aws_api.AWSApi)
|
597
636
|
self.account_vpcs = [
|
598
637
|
{
|
599
638
|
"vpc_id": "vpc1",
|
@@ -610,7 +649,7 @@ class TestBuildDesiredStateVpcMesh(testslide.TestCase):
|
|
610
649
|
]
|
611
650
|
self.addCleanup(testslide.mock_callable.unpatch_all_callable_mocks)
|
612
651
|
|
613
|
-
def test_all_fine(self):
|
652
|
+
def test_all_fine(self) -> None:
|
614
653
|
expected = [
|
615
654
|
{
|
616
655
|
"connection_provider": "account-vpc-mesh",
|
@@ -652,7 +691,10 @@ class TestBuildDesiredStateVpcMesh(testslide.TestCase):
|
|
652
691
|
},
|
653
692
|
]
|
654
693
|
self.vpc_mesh_single_cluster.for_call(
|
655
|
-
self.clusters[0],
|
694
|
+
self.clusters[0],
|
695
|
+
self.ocm,
|
696
|
+
self.awsapi,
|
697
|
+
None,
|
656
698
|
).to_return_value(expected)
|
657
699
|
|
658
700
|
rs = sut.build_desired_state_vpc_mesh(
|
@@ -663,25 +705,31 @@ class TestBuildDesiredStateVpcMesh(testslide.TestCase):
|
|
663
705
|
)
|
664
706
|
self.assertEqual(rs, (expected, False))
|
665
707
|
|
666
|
-
def test_cluster_raises(self):
|
708
|
+
def test_cluster_raises(self) -> None:
|
667
709
|
self.vpc_mesh_single_cluster.to_raise(
|
668
710
|
sut.BadTerraformPeeringState("This is wrong")
|
669
711
|
)
|
670
712
|
rs = sut.build_desired_state_vpc_mesh(
|
671
|
-
self.clusters,
|
713
|
+
self.clusters,
|
714
|
+
self.ocm_map,
|
715
|
+
self.awsapi,
|
716
|
+
None,
|
672
717
|
)
|
673
718
|
self.assertEqual(rs, ([], True))
|
674
719
|
|
675
|
-
def test_cluster_raises_unexpected(self):
|
720
|
+
def test_cluster_raises_unexpected(self) -> None:
|
676
721
|
self.vpc_mesh_single_cluster.to_raise(ValueError("Nope"))
|
677
722
|
with self.assertRaises(ValueError):
|
678
723
|
sut.build_desired_state_vpc_mesh(
|
679
|
-
self.clusters,
|
724
|
+
self.clusters,
|
725
|
+
self.ocm_map,
|
726
|
+
self.awsapi,
|
727
|
+
None,
|
680
728
|
)
|
681
729
|
|
682
730
|
|
683
731
|
class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
684
|
-
def setUp(self):
|
732
|
+
def setUp(self) -> None:
|
685
733
|
super().setUp()
|
686
734
|
self.cluster = {
|
687
735
|
"name": "clustername",
|
@@ -728,7 +776,7 @@ class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
|
728
776
|
]
|
729
777
|
},
|
730
778
|
}
|
731
|
-
self.awsapi = testslide.StrictMock(aws_api.AWSApi)
|
779
|
+
self.awsapi: aws_api.AWSApi = testslide.StrictMock(aws_api.AWSApi)
|
732
780
|
self.mock_constructor(aws_api, "AWSApi").to_return_value(self.awsapi)
|
733
781
|
self.find_matching_peering = self.mock_callable(sut, "find_matching_peering")
|
734
782
|
self.aws_account = {
|
@@ -749,8 +797,8 @@ class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
|
749
797
|
"assume_region": "mars-hellas-1",
|
750
798
|
"assume_cidr": "172.25.0.0/12",
|
751
799
|
}
|
752
|
-
self.cluster["peering"]["connections"][0]["cluster"] = self.peer_cluster
|
753
|
-
self.cluster["peering"]["connections"][0]["account"] = self.peer_account
|
800
|
+
self.cluster["peering"]["connections"][0]["cluster"] = self.peer_cluster # type: ignore
|
801
|
+
self.cluster["peering"]["connections"][0]["account"] = self.peer_account # type: ignore
|
754
802
|
self.peer_vpc = {
|
755
803
|
"cidr_block": "172.30.0.0/12",
|
756
804
|
"vpc_id": "peervpcid",
|
@@ -758,8 +806,8 @@ class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
|
758
806
|
}
|
759
807
|
self.maxDiff = None
|
760
808
|
self.addCleanup(testslide.mock_callable.unpatch_all_callable_mocks)
|
761
|
-
self.ocm = testslide.StrictMock(template=ocm.OCM)
|
762
|
-
self.ocm.get_aws_infrastructure_access_terraform_assume_role = (
|
809
|
+
self.ocm: ocm.OCM = testslide.StrictMock(template=ocm.OCM)
|
810
|
+
self.ocm.get_aws_infrastructure_access_terraform_assume_role = ( # type: ignore
|
763
811
|
lambda cluster, uid, tfuser: self.peer_account["assume_role"]
|
764
812
|
)
|
765
813
|
self.account_vpcs = [
|
@@ -777,7 +825,7 @@ class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
|
777
825
|
},
|
778
826
|
]
|
779
827
|
|
780
|
-
def test_one_cluster(self):
|
828
|
+
def test_one_cluster(self) -> None:
|
781
829
|
req_account = {
|
782
830
|
**self.peer_account,
|
783
831
|
"assume_region": "mars-plain-1",
|
@@ -842,11 +890,14 @@ class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
|
842
890
|
]
|
843
891
|
|
844
892
|
rs = sut.build_desired_state_vpc_mesh_single_cluster(
|
845
|
-
self.cluster,
|
893
|
+
self.cluster,
|
894
|
+
self.ocm,
|
895
|
+
self.awsapi,
|
896
|
+
None,
|
846
897
|
)
|
847
898
|
self.assertEqual(rs, expected)
|
848
899
|
|
849
|
-
def test_one_cluster_private_hcp(self):
|
900
|
+
def test_one_cluster_private_hcp(self) -> None:
|
850
901
|
self.cluster["spec"] = {
|
851
902
|
"region": "mars-plain-1",
|
852
903
|
"hypershift": True,
|
@@ -920,14 +971,14 @@ class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
|
920
971
|
)
|
921
972
|
self.assertEqual(rs, expected)
|
922
973
|
|
923
|
-
def test_no_peering_connections(self):
|
924
|
-
self.cluster["peering"]["connections"] = []
|
974
|
+
def test_no_peering_connections(self) -> None:
|
975
|
+
self.cluster["peering"]["connections"] = [] # type: ignore
|
925
976
|
rs = sut.build_desired_state_vpc_mesh_single_cluster(
|
926
977
|
self.cluster, self.ocm, self.awsapi, None
|
927
978
|
)
|
928
979
|
self.assertEqual(rs, [])
|
929
980
|
|
930
|
-
def test_no_peer_vpc_id(self):
|
981
|
+
def test_no_peer_vpc_id(self) -> None:
|
931
982
|
self.mock_callable(self.awsapi, "get_cluster_vpc_details").to_return_value((
|
932
983
|
None,
|
933
984
|
[None],
|
@@ -942,7 +993,7 @@ class TestBuildDesiredStateVpcMeshSingleCluster(testslide.TestCase):
|
|
942
993
|
|
943
994
|
|
944
995
|
class TestBuildDesiredStateVpc(testslide.TestCase):
|
945
|
-
def setUp(self):
|
996
|
+
def setUp(self) -> None:
|
946
997
|
super().setUp()
|
947
998
|
self.peer = {
|
948
999
|
"vpc": "172.17.0.0/12",
|
@@ -1007,13 +1058,13 @@ class TestBuildDesiredStateVpc(testslide.TestCase):
|
|
1007
1058
|
]
|
1008
1059
|
},
|
1009
1060
|
}
|
1010
|
-
self.clusters[0]["peering"]["connections"][0]["cluster"] = self.peer_cluster
|
1061
|
+
self.clusters[0]["peering"]["connections"][0]["cluster"] = self.peer_cluster # type: ignore
|
1011
1062
|
self.build_single_cluster = self.mock_callable(
|
1012
1063
|
sut, "build_desired_state_single_cluster"
|
1013
1064
|
)
|
1014
1065
|
self.ocm = testslide.StrictMock(template=ocm.OCM)
|
1015
|
-
self.ocm_map = {"clustername": self.ocm}
|
1016
|
-
self.awsapi = testslide.StrictMock(aws_api.AWSApi)
|
1066
|
+
self.ocm_map: ocm.OCMMap = {"clustername": self.ocm} # type: ignore
|
1067
|
+
self.awsapi: aws_api.AWSApi = testslide.StrictMock(aws_api.AWSApi)
|
1017
1068
|
|
1018
1069
|
self.build_single_cluster = self.mock_callable(
|
1019
1070
|
sut, "build_desired_state_vpc_single_cluster"
|
@@ -1021,7 +1072,7 @@ class TestBuildDesiredStateVpc(testslide.TestCase):
|
|
1021
1072
|
self.addCleanup(testslide.mock_callable.unpatch_all_callable_mocks)
|
1022
1073
|
self.maxDiff = None
|
1023
1074
|
|
1024
|
-
def test_all_fine(self):
|
1075
|
+
def test_all_fine(self) -> None:
|
1025
1076
|
expected = [
|
1026
1077
|
{
|
1027
1078
|
"accepter": {
|
@@ -1067,7 +1118,7 @@ class TestBuildDesiredStateVpc(testslide.TestCase):
|
|
1067
1118
|
)
|
1068
1119
|
self.assertEqual(rs, (expected, False))
|
1069
1120
|
|
1070
|
-
def test_cluster_fails(self):
|
1121
|
+
def test_cluster_fails(self) -> None:
|
1071
1122
|
self.build_single_cluster.to_raise(
|
1072
1123
|
sut.BadTerraformPeeringState("I have failed")
|
1073
1124
|
)
|
@@ -1079,10 +1130,10 @@ class TestBuildDesiredStateVpc(testslide.TestCase):
|
|
1079
1130
|
([], True),
|
1080
1131
|
)
|
1081
1132
|
|
1082
|
-
def test_error_persists(self):
|
1133
|
+
def test_error_persists(self) -> None:
|
1083
1134
|
self.clusters.append(self.clusters[0].copy())
|
1084
1135
|
self.clusters[1]["name"] = "afailingcluster"
|
1085
|
-
self.ocm_map["afailingcluster"] = self.ocm
|
1136
|
+
self.ocm_map["afailingcluster"] = self.ocm # type: ignore
|
1086
1137
|
self.build_single_cluster.for_call(
|
1087
1138
|
self.clusters[0], self.ocm, self.awsapi, None
|
1088
1139
|
).to_return_value([{"a dict": "a value"}]).and_assert_called_once()
|
@@ -1100,10 +1151,10 @@ class TestBuildDesiredStateVpc(testslide.TestCase):
|
|
1100
1151
|
([{"a dict": "a value"}], True),
|
1101
1152
|
)
|
1102
1153
|
|
1103
|
-
def test_other_exceptions_raise(self):
|
1154
|
+
def test_other_exceptions_raise(self) -> None:
|
1104
1155
|
self.clusters.append(self.clusters[0].copy())
|
1105
1156
|
self.clusters[1]["name"] = "afailingcluster"
|
1106
|
-
self.ocm_map["afailingcluster"] = self.ocm
|
1157
|
+
self.ocm_map["afailingcluster"] = self.ocm # type: ignore
|
1107
1158
|
self.build_single_cluster.for_call(
|
1108
1159
|
self.clusters[0], self.ocm, self.awsapi, None
|
1109
1160
|
).to_raise(ValueError("I am not planned!")).and_assert_called_once()
|
@@ -1114,7 +1165,7 @@ class TestBuildDesiredStateVpc(testslide.TestCase):
|
|
1114
1165
|
|
1115
1166
|
|
1116
1167
|
class TestBuildDesiredStateVpcSingleCluster(testslide.TestCase):
|
1117
|
-
def setUp(self):
|
1168
|
+
def setUp(self) -> None:
|
1118
1169
|
super().setUp()
|
1119
1170
|
self.peer = {
|
1120
1171
|
"vpc": "172.17.0.0/12",
|
@@ -1177,20 +1228,20 @@ class TestBuildDesiredStateVpcSingleCluster(testslide.TestCase):
|
|
1177
1228
|
]
|
1178
1229
|
},
|
1179
1230
|
}
|
1180
|
-
self.cluster["peering"]["connections"][0]["cluster"] = self.peer_cluster
|
1231
|
+
self.cluster["peering"]["connections"][0]["cluster"] = self.peer_cluster # type: ignore
|
1181
1232
|
self.build_single_cluster = self.mock_callable(
|
1182
1233
|
sut, "build_desired_state_single_cluster"
|
1183
1234
|
)
|
1184
|
-
self.ocm = testslide.StrictMock(template=ocm.OCM)
|
1185
|
-
self.awsapi = testslide.StrictMock(aws_api.AWSApi)
|
1235
|
+
self.ocm: ocm.OCM = testslide.StrictMock(template=ocm.OCM)
|
1236
|
+
self.awsapi: aws_api.AWSApi = testslide.StrictMock(aws_api.AWSApi)
|
1186
1237
|
self.mock_constructor(aws_api, "AWSApi").to_return_value(self.awsapi)
|
1187
|
-
self.ocm.get_aws_infrastructure_access_terraform_assume_role = (
|
1238
|
+
self.ocm.get_aws_infrastructure_access_terraform_assume_role = ( # type: ignore
|
1188
1239
|
lambda cluster, uid, tfuser: self.aws_account["assume_role"]
|
1189
1240
|
)
|
1190
1241
|
self.addCleanup(testslide.mock_callable.unpatch_all_callable_mocks)
|
1191
1242
|
self.maxDiff = None
|
1192
1243
|
|
1193
|
-
def test_all_fine(self):
|
1244
|
+
def test_all_fine(self) -> None:
|
1194
1245
|
expected = [
|
1195
1246
|
{
|
1196
1247
|
"accepter": {
|
@@ -1252,7 +1303,7 @@ class TestBuildDesiredStateVpcSingleCluster(testslide.TestCase):
|
|
1252
1303
|
)
|
1253
1304
|
self.assertEqual(rs, expected)
|
1254
1305
|
|
1255
|
-
def test_private_hcp(self):
|
1306
|
+
def test_private_hcp(self) -> None:
|
1256
1307
|
self.cluster["spec"] = {
|
1257
1308
|
"region": "mars-plain-1",
|
1258
1309
|
"hypershift": True,
|
@@ -1319,16 +1370,19 @@ class TestBuildDesiredStateVpcSingleCluster(testslide.TestCase):
|
|
1319
1370
|
)
|
1320
1371
|
self.assertEqual(rs, expected)
|
1321
1372
|
|
1322
|
-
def test_different_provider(self):
|
1323
|
-
self.cluster["peering"]["connections"][0]["provider"] = "something-else"
|
1373
|
+
def test_different_provider(self) -> None:
|
1374
|
+
self.cluster["peering"]["connections"][0]["provider"] = "something-else" # type: ignore
|
1324
1375
|
self.assertEqual(
|
1325
1376
|
sut.build_desired_state_vpc_single_cluster(
|
1326
|
-
self.cluster,
|
1377
|
+
self.cluster,
|
1378
|
+
self.ocm,
|
1379
|
+
self.awsapi,
|
1380
|
+
None,
|
1327
1381
|
),
|
1328
1382
|
[],
|
1329
1383
|
)
|
1330
1384
|
|
1331
|
-
def test_no_vpc_id(self):
|
1385
|
+
def test_no_vpc_id(self) -> None:
|
1332
1386
|
self.mock_callable(self.awsapi, "get_cluster_vpc_details").to_return_value((
|
1333
1387
|
None,
|
1334
1388
|
None,
|
@@ -1345,7 +1399,7 @@ class TestBuildDesiredStateVpcSingleCluster(testslide.TestCase):
|
|
1345
1399
|
)
|
1346
1400
|
assert desired_state == []
|
1347
1401
|
|
1348
|
-
def test_aws_exception(self):
|
1402
|
+
def test_aws_exception(self) -> None:
|
1349
1403
|
exc_txt = "AWS Problem!"
|
1350
1404
|
self.mock_callable(self.awsapi, "get_cluster_vpc_details").to_raise(
|
1351
1405
|
Exception(exc_txt)
|
@@ -1357,5 +1411,8 @@ class TestBuildDesiredStateVpcSingleCluster(testslide.TestCase):
|
|
1357
1411
|
|
1358
1412
|
with pytest.raises(Exception, match=exc_txt):
|
1359
1413
|
sut.build_desired_state_vpc_single_cluster(
|
1360
|
-
self.cluster,
|
1414
|
+
self.cluster,
|
1415
|
+
self.ocm,
|
1416
|
+
self.awsapi,
|
1417
|
+
None,
|
1361
1418
|
)
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc830.dist-info → qontract_reconcile-0.10.1rc832.dist-info}/top_level.txt
RENAMED
File without changes
|