qontract-reconcile 0.10.2.dev19__py3-none-any.whl → 0.10.2.dev20__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.dev19.dist-info → qontract_reconcile-0.10.2.dev20.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev19.dist-info → qontract_reconcile-0.10.2.dev20.dist-info}/RECORD +7 -7
- reconcile/external_resources/integration.py +9 -4
- reconcile/external_resources/manager.py +40 -8
- reconcile/external_resources/model.py +11 -0
- {qontract_reconcile-0.10.2.dev19.dist-info → qontract_reconcile-0.10.2.dev20.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev19.dist-info → qontract_reconcile-0.10.2.dev20.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev19.dist-info → qontract_reconcile-0.10.2.dev20.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.2.
|
3
|
+
Version: 0.10.2.dev20
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
|
6
6
|
Project-URL: repository, https://github.com/app-sre/qontract-reconcile
|
{qontract_reconcile-0.10.2.dev19.dist-info → qontract_reconcile-0.10.2.dev20.dist-info}/RECORD
RENAMED
@@ -197,12 +197,12 @@ reconcile/endpoints_discovery/merge_request_manager.py,sha256=wUMsumxv8RnWaRatta
|
|
197
197
|
reconcile/external_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
198
198
|
reconcile/external_resources/aws.py,sha256=NSaOeHqFEcMaMxNjJwuQZosolgsJ8XRVvwkEEBj9vrw,7730
|
199
199
|
reconcile/external_resources/factories.py,sha256=TyJMaijDfPIFYks9i6dhKN7nSR1BoCkoBs1iPExKpcE,5493
|
200
|
-
reconcile/external_resources/integration.py,sha256=
|
200
|
+
reconcile/external_resources/integration.py,sha256=JF38M7R0Z4ADUTx57TZqSZH9k_xpPlbAxQAcGyIISuM,6925
|
201
201
|
reconcile/external_resources/integration_secrets_sync.py,sha256=dX09O3r6KURziUYYfiki10orNjOGVma-XojhVqd0ww4,1667
|
202
|
-
reconcile/external_resources/manager.py,sha256=
|
202
|
+
reconcile/external_resources/manager.py,sha256=q7Ezp-g3MhpH_t8zpNMH5wCzHvh-nERpHzvBPA1G1ng,17031
|
203
203
|
reconcile/external_resources/meta.py,sha256=noaytFzmShpzLA_ebGh7wuP45mOfHIOnnoUxivjDa1I,672
|
204
204
|
reconcile/external_resources/metrics.py,sha256=KiBjMUaN_z0cSkF_7Ar_a8RiuiwVqjyMcVdISlxhzXE,3898
|
205
|
-
reconcile/external_resources/model.py,sha256=
|
205
|
+
reconcile/external_resources/model.py,sha256=KdB3eYlopWOLQmvL1aICjm-kAPIlY2N_zSikcCFBQpk,11751
|
206
206
|
reconcile/external_resources/reconciler.py,sha256=K9QvbQCIOCuOHnPIxQE_P_jFtrkF3dGo8d_cCCh08Ys,8973
|
207
207
|
reconcile/external_resources/secrets_sync.py,sha256=50fK4fzgSz-K8uy5_DQQWA_ju_rTDYAC2HRymgfY7TA,16344
|
208
208
|
reconcile/external_resources/state.py,sha256=ye8yjMoCtTHSRhDH7skFLDIHIuYTjisWYCTJrwnmbEw,9565
|
@@ -766,7 +766,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
766
766
|
tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
|
767
767
|
tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
|
768
768
|
tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
|
769
|
-
qontract_reconcile-0.10.2.
|
770
|
-
qontract_reconcile-0.10.2.
|
771
|
-
qontract_reconcile-0.10.2.
|
772
|
-
qontract_reconcile-0.10.2.
|
769
|
+
qontract_reconcile-0.10.2.dev20.dist-info/METADATA,sha256=dMYY6LBhL21XhtZxss8dwyRBMyK2ce1Yh7UvoUBK2bM,24665
|
770
|
+
qontract_reconcile-0.10.2.dev20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
771
|
+
qontract_reconcile-0.10.2.dev20.dist-info/entry_points.txt,sha256=JniHZPadNOILPyfSl0LF2YSp3Db7K2_W2CN7i9f3Gos,540
|
772
|
+
qontract_reconcile-0.10.2.dev20.dist-info/RECORD,,
|
@@ -3,6 +3,7 @@ from collections.abc import Callable
|
|
3
3
|
from typing import Any
|
4
4
|
|
5
5
|
from reconcile.external_resources.manager import (
|
6
|
+
ExternalResourceDryRunsValidator,
|
6
7
|
ExternalResourcesInventory,
|
7
8
|
ExternalResourcesManager,
|
8
9
|
setup_factories,
|
@@ -89,6 +90,10 @@ def create_er_manager(
|
|
89
90
|
m_inventory = load_module_inventory(get_modules())
|
90
91
|
namespaces = [ns for ns in get_namespaces() if ns.external_resources]
|
91
92
|
er_inventory = ExternalResourcesInventory(namespaces)
|
93
|
+
state_manager = ExternalResourcesStateDynamoDB(
|
94
|
+
aws_api=aws_api,
|
95
|
+
table_name=er_settings.state_dynamodb_table,
|
96
|
+
)
|
92
97
|
|
93
98
|
if not workers_cluster:
|
94
99
|
workers_cluster = er_settings.workers_cluster.name
|
@@ -104,10 +109,7 @@ def create_er_manager(
|
|
104
109
|
),
|
105
110
|
er_inventory=er_inventory,
|
106
111
|
module_inventory=m_inventory,
|
107
|
-
state_manager=
|
108
|
-
aws_api=aws_api,
|
109
|
-
table_name=er_settings.state_dynamodb_table,
|
110
|
-
),
|
112
|
+
state_manager=state_manager,
|
111
113
|
reconciler=K8sExternalResourcesReconciler(
|
112
114
|
controller=build_job_controller(
|
113
115
|
integration=QONTRACT_INTEGRATION,
|
@@ -128,6 +130,9 @@ def create_er_manager(
|
|
128
130
|
thread_pool_size=thread_pool_size,
|
129
131
|
dry_run=dry_run,
|
130
132
|
),
|
133
|
+
dry_runs_validator=ExternalResourceDryRunsValidator(
|
134
|
+
state_manager, er_inventory
|
135
|
+
),
|
131
136
|
)
|
132
137
|
|
133
138
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import logging
|
2
|
+
from collections import Counter
|
2
3
|
from collections.abc import Iterable
|
3
4
|
from datetime import UTC, datetime
|
4
5
|
|
@@ -19,6 +20,7 @@ from reconcile.external_resources.model import (
|
|
19
20
|
ExternalResourceKey,
|
20
21
|
ExternalResourceModuleConfiguration,
|
21
22
|
ExternalResourceOrphanedResourcesError,
|
23
|
+
ExternalResourceOutputResourceNameDuplications,
|
22
24
|
ExternalResourcesInventory,
|
23
25
|
ExternalResourceValidationError,
|
24
26
|
ModuleInventory,
|
@@ -73,6 +75,41 @@ def setup_factories(
|
|
73
75
|
return of
|
74
76
|
|
75
77
|
|
78
|
+
class ExternalResourceDryRunsValidator:
|
79
|
+
def __init__(
|
80
|
+
self,
|
81
|
+
state_manager: ExternalResourcesStateDynamoDB,
|
82
|
+
er_inventory: ExternalResourcesInventory,
|
83
|
+
):
|
84
|
+
self.state_mgr = state_manager
|
85
|
+
self.er_inventory = er_inventory
|
86
|
+
|
87
|
+
def _check_output_resource_name_duplications(
|
88
|
+
self,
|
89
|
+
) -> None:
|
90
|
+
specs = Counter(
|
91
|
+
(
|
92
|
+
spec.cluster_name,
|
93
|
+
spec.namespace_name,
|
94
|
+
spec.output_resource_name,
|
95
|
+
)
|
96
|
+
for spec in self.er_inventory.values()
|
97
|
+
)
|
98
|
+
if duplicates := [key for key, count in specs.items() if count > 1]:
|
99
|
+
raise ExternalResourceOutputResourceNameDuplications(duplicates)
|
100
|
+
|
101
|
+
def _check_orphaned_objects(self) -> None:
|
102
|
+
state_keys = self.state_mgr.get_all_resource_keys()
|
103
|
+
inventory_keys = set(self.er_inventory.keys())
|
104
|
+
orphans = state_keys - inventory_keys
|
105
|
+
if len(orphans) > 0:
|
106
|
+
raise ExternalResourceOrphanedResourcesError(orphans)
|
107
|
+
|
108
|
+
def validate(self) -> None:
|
109
|
+
self._check_orphaned_objects()
|
110
|
+
self._check_output_resource_name_duplications()
|
111
|
+
|
112
|
+
|
76
113
|
class ExternalResourcesManager:
|
77
114
|
def __init__(
|
78
115
|
self,
|
@@ -84,6 +121,7 @@ class ExternalResourcesManager:
|
|
84
121
|
er_inventory: ExternalResourcesInventory,
|
85
122
|
factories: ObjectFactory[ExternalResourceFactory],
|
86
123
|
secrets_reconciler: InClusterSecretsReconciler,
|
124
|
+
dry_runs_validator: ExternalResourceDryRunsValidator,
|
87
125
|
thread_pool_size: int,
|
88
126
|
) -> None:
|
89
127
|
self.state_mgr = state_manager
|
@@ -96,6 +134,7 @@ class ExternalResourcesManager:
|
|
96
134
|
self.secrets_reconciler = secrets_reconciler
|
97
135
|
self.errors: dict[ExternalResourceKey, ExternalResourceValidationError] = {}
|
98
136
|
self.thread_pool_size = thread_pool_size
|
137
|
+
self.dry_runs_validator = dry_runs_validator
|
99
138
|
|
100
139
|
def _get_reconcile_action(
|
101
140
|
self, reconciliation: Reconciliation, state: ExternalResourceState
|
@@ -199,13 +238,6 @@ class ExternalResourcesManager:
|
|
199
238
|
to_reconcile.add(r)
|
200
239
|
return to_reconcile
|
201
240
|
|
202
|
-
def _check_orphaned_objects(self) -> None:
|
203
|
-
state_keys = self.state_mgr.get_all_resource_keys()
|
204
|
-
inventory_keys = set(self.er_inventory.keys())
|
205
|
-
orphans = state_keys - inventory_keys
|
206
|
-
if len(orphans) > 0:
|
207
|
-
raise ExternalResourceOrphanedResourcesError(orphans)
|
208
|
-
|
209
241
|
def _get_reconciliation_status(
|
210
242
|
self,
|
211
243
|
r: Reconciliation,
|
@@ -374,7 +406,7 @@ class ExternalResourcesManager:
|
|
374
406
|
self._sync_secrets(to_sync_keys=to_sync_keys | pending_sync_keys)
|
375
407
|
|
376
408
|
def handle_dry_run_resources(self) -> None:
|
377
|
-
self.
|
409
|
+
self.dry_runs_validator.validate()
|
378
410
|
desired_r = self._get_desired_objects_reconciliations()
|
379
411
|
deleted_r = self._get_deleted_objects_reconciliations()
|
380
412
|
reconciliations = desired_r.union(deleted_r)
|
@@ -45,6 +45,17 @@ class ExternalResourceOrphanedResourcesError(Exception):
|
|
45
45
|
super().__init__("".join(msg))
|
46
46
|
|
47
47
|
|
48
|
+
class ExternalResourceOutputResourceNameDuplications(Exception):
|
49
|
+
def __init__(self, duplicates: Iterable[tuple[str, str, str]]) -> None:
|
50
|
+
msg = [
|
51
|
+
"There are output_resource_name attribute duplications. ",
|
52
|
+
"output_resource_name must be unique within a cluster/namespace.\n"
|
53
|
+
"Duplications:\n",
|
54
|
+
"\n".join(map(str, duplicates)),
|
55
|
+
]
|
56
|
+
super().__init__("".join(msg))
|
57
|
+
|
58
|
+
|
48
59
|
class ExternalResourceValidationError(Exception):
|
49
60
|
errors: list[str] = []
|
50
61
|
|
{qontract_reconcile-0.10.2.dev19.dist-info → qontract_reconcile-0.10.2.dev20.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|