qontract-reconcile 0.10.1rc1198__py3-none-any.whl → 0.10.1rc1200__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.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.dist-info}/RECORD +10 -10
- reconcile/external_resources/aws.py +19 -0
- reconcile/external_resources/factories.py +13 -0
- reconcile/external_resources/manager.py +25 -7
- reconcile/external_resources/model.py +25 -12
- reconcile/external_resources/secrets_sync.py +5 -3
- {qontract_reconcile-0.10.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.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.1rc1200
|
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.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.dist-info}/RECORD
RENAMED
@@ -192,16 +192,16 @@ reconcile/endpoints_discovery/integration.py,sha256=znfnlm8bZesfcNbQnaR2aaVM-DTB
|
|
192
192
|
reconcile/endpoints_discovery/merge_request.py,sha256=_yLb4tnvoZMCko8rta2C_CvOInJa9pa3HzSmHNtjgGU,2978
|
193
193
|
reconcile/endpoints_discovery/merge_request_manager.py,sha256=wUMsumxv8RnWaRattax4HfoRlhtVzmgro3GiJJ1C4Vc,6392
|
194
194
|
reconcile/external_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
195
|
-
reconcile/external_resources/aws.py,sha256=
|
196
|
-
reconcile/external_resources/factories.py,sha256=
|
195
|
+
reconcile/external_resources/aws.py,sha256=NSaOeHqFEcMaMxNjJwuQZosolgsJ8XRVvwkEEBj9vrw,7730
|
196
|
+
reconcile/external_resources/factories.py,sha256=TyJMaijDfPIFYks9i6dhKN7nSR1BoCkoBs1iPExKpcE,5493
|
197
197
|
reconcile/external_resources/integration.py,sha256=gBVO5dE8JyZ3xYcYik-MTIp_18oU7_hpYc_oztyfElQ,6753
|
198
198
|
reconcile/external_resources/integration_secrets_sync.py,sha256=dX09O3r6KURziUYYfiki10orNjOGVma-XojhVqd0ww4,1667
|
199
|
-
reconcile/external_resources/manager.py,sha256=
|
199
|
+
reconcile/external_resources/manager.py,sha256=HATI3oWDyxIt7k_SynXqk4CYQzCJHGPmig1XEJoNOA0,15832
|
200
200
|
reconcile/external_resources/meta.py,sha256=noaytFzmShpzLA_ebGh7wuP45mOfHIOnnoUxivjDa1I,672
|
201
201
|
reconcile/external_resources/metrics.py,sha256=8MZgNtNZzIRSYTX97KEUIUTETZBhitULzWxbShGyMO8,3193
|
202
|
-
reconcile/external_resources/model.py,sha256=
|
202
|
+
reconcile/external_resources/model.py,sha256=YJylbAhetN9szpLUFd9jFqxCRMvSWXVxSC9OMQNV-wg,11316
|
203
203
|
reconcile/external_resources/reconciler.py,sha256=K9QvbQCIOCuOHnPIxQE_P_jFtrkF3dGo8d_cCCh08Ys,8973
|
204
|
-
reconcile/external_resources/secrets_sync.py,sha256=
|
204
|
+
reconcile/external_resources/secrets_sync.py,sha256=H8JfI3JW1XEau1jqv15AhYg49mCZeHwZmqMzMv_6tFc,16344
|
205
205
|
reconcile/external_resources/state.py,sha256=7DBzVhIvYqeZWrWapmU_bXXftTQa_m-EOwJFVlIFnDw,9583
|
206
206
|
reconcile/glitchtip/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
207
207
|
reconcile/glitchtip/integration.py,sha256=XtewM9nfTPLnPSpYebP50GrveYOnhTvKNq3seSvL6u8,8343
|
@@ -882,8 +882,8 @@ tools/test/test_qontract_cli.py,sha256=iuzKbQ6ahinvjoQmQLBrG4shey0z-1rB6qCgS8T6d
|
|
882
882
|
tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
|
883
883
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
884
884
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
885
|
-
qontract_reconcile-0.10.
|
886
|
-
qontract_reconcile-0.10.
|
887
|
-
qontract_reconcile-0.10.
|
888
|
-
qontract_reconcile-0.10.
|
889
|
-
qontract_reconcile-0.10.
|
885
|
+
qontract_reconcile-0.10.1rc1200.dist-info/METADATA,sha256=TsJMZagQbxyhlVsDImDJTdadVxpB3agV14BYdeZkSo4,2213
|
886
|
+
qontract_reconcile-0.10.1rc1200.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
887
|
+
qontract_reconcile-0.10.1rc1200.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
|
888
|
+
qontract_reconcile-0.10.1rc1200.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
889
|
+
qontract_reconcile-0.10.1rc1200.dist-info/RECORD,,
|
@@ -3,6 +3,7 @@ from typing import Any
|
|
3
3
|
|
4
4
|
from reconcile.external_resources.model import (
|
5
5
|
ExternalResource,
|
6
|
+
ExternalResourceKey,
|
6
7
|
ExternalResourcesInventory,
|
7
8
|
)
|
8
9
|
from reconcile.utils.external_resource_spec import (
|
@@ -25,6 +26,13 @@ class AWSResourceFactory(ABC):
|
|
25
26
|
@abstractmethod
|
26
27
|
def validate(self, resource: ExternalResource) -> None: ...
|
27
28
|
|
29
|
+
def find_linked_resources(
|
30
|
+
self, spec: ExternalResourceSpec
|
31
|
+
) -> set[ExternalResourceKey]:
|
32
|
+
"""Method to find dependant resources. Resources in this list
|
33
|
+
will be reconciled every time the parent resource finishes its reconciliation."""
|
34
|
+
return set()
|
35
|
+
|
28
36
|
|
29
37
|
class AWSDefaultResourceFactory(AWSResourceFactory):
|
30
38
|
def resolve(self, spec: ExternalResourceSpec) -> dict[str, Any]:
|
@@ -136,6 +144,17 @@ class AWSRdsFactory(AWSDefaultResourceFactory):
|
|
136
144
|
|
137
145
|
def validate(self, resource: ExternalResource) -> None: ...
|
138
146
|
|
147
|
+
def find_linked_resources(
|
148
|
+
self, spec: ExternalResourceSpec
|
149
|
+
) -> set[ExternalResourceKey]:
|
150
|
+
return {
|
151
|
+
k
|
152
|
+
for k, s in self.er_inventory.items()
|
153
|
+
if s.provision_provider == "aws"
|
154
|
+
and s.provider == "rds"
|
155
|
+
and s.resource["replica_source"] == spec.identifier
|
156
|
+
}
|
157
|
+
|
139
158
|
|
140
159
|
class AWSMskFactory(AWSDefaultResourceFactory):
|
141
160
|
def _get_source_db_spec(
|
@@ -60,6 +60,13 @@ class ExternalResourceFactory(ABC):
|
|
60
60
|
def validate_external_resource(self, resource: ExternalResource) -> None:
|
61
61
|
pass
|
62
62
|
|
63
|
+
def find_linked_resources(
|
64
|
+
self, spec: ExternalResourceSpec
|
65
|
+
) -> set[ExternalResourceKey]:
|
66
|
+
"""Method to find dependant resources. Resources in this list
|
67
|
+
will be reconciled every time the parent resource finishes its reconciliation."""
|
68
|
+
return set()
|
69
|
+
|
63
70
|
|
64
71
|
class ModuleProvisionDataFactory(ABC):
|
65
72
|
@abstractmethod
|
@@ -148,3 +155,9 @@ class AWSExternalResourceFactory(ExternalResourceFactory):
|
|
148
155
|
def validate_external_resource(self, resource: ExternalResource) -> None:
|
149
156
|
f = self.resource_factories.get_factory(resource.provision.provider)
|
150
157
|
f.validate(resource)
|
158
|
+
|
159
|
+
def find_linked_resources(
|
160
|
+
self, spec: ExternalResourceSpec
|
161
|
+
) -> set[ExternalResourceKey]:
|
162
|
+
f = self.resource_factories.get_factory(spec.provider)
|
163
|
+
return f.find_linked_resources(spec)
|
@@ -18,6 +18,7 @@ from reconcile.external_resources.model import (
|
|
18
18
|
ExternalResource,
|
19
19
|
ExternalResourceKey,
|
20
20
|
ExternalResourceModuleConfiguration,
|
21
|
+
ExternalResourceOrphanedResourcesError,
|
21
22
|
ExternalResourcesInventory,
|
22
23
|
ExternalResourceValidationError,
|
23
24
|
ModuleInventory,
|
@@ -161,7 +162,7 @@ class ExternalResourcesManager:
|
|
161
162
|
continue
|
162
163
|
module = self.module_inventory.get_from_spec(spec)
|
163
164
|
try:
|
164
|
-
resource = self._build_external_resource(spec
|
165
|
+
resource = self._build_external_resource(spec)
|
165
166
|
except ExternalResourceValidationError as e:
|
166
167
|
self.errors[key] = e
|
167
168
|
continue
|
@@ -169,11 +170,12 @@ class ExternalResourcesManager:
|
|
169
170
|
reconciliation = Reconciliation(
|
170
171
|
key=key,
|
171
172
|
resource_hash=resource.hash(),
|
172
|
-
input=
|
173
|
+
input=resource.json(),
|
173
174
|
action=Action.APPLY,
|
174
175
|
module_configuration=ExternalResourceModuleConfiguration.resolve_configuration(
|
175
176
|
module, spec, self.settings
|
176
177
|
),
|
178
|
+
linked_resources=self._find_linked_resources(spec),
|
177
179
|
)
|
178
180
|
r.add(reconciliation)
|
179
181
|
return r
|
@@ -197,6 +199,13 @@ class ExternalResourcesManager:
|
|
197
199
|
to_reconcile.add(r)
|
198
200
|
return to_reconcile
|
199
201
|
|
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
|
+
|
200
209
|
def _get_reconciliation_status(
|
201
210
|
self,
|
202
211
|
r: Reconciliation,
|
@@ -273,6 +282,13 @@ class ExternalResourcesManager:
|
|
273
282
|
state.update_resource_status(reconciliation_status)
|
274
283
|
self.state_mgr.set_external_resource_state(state)
|
275
284
|
|
285
|
+
if r.linked_resources:
|
286
|
+
for lr in r.linked_resources:
|
287
|
+
lrs = self.state_mgr.get_external_resource_state(lr)
|
288
|
+
if not lrs.resource_status.is_in_progress:
|
289
|
+
lrs.resource_status = ResourceStatus.RECONCILIATION_REQUESTED
|
290
|
+
self.state_mgr.set_external_resource_state(lrs)
|
291
|
+
|
276
292
|
def _set_resource_reconciliation_in_progress(
|
277
293
|
self, r: Reconciliation, state: ExternalResourceState
|
278
294
|
) -> None:
|
@@ -317,16 +333,17 @@ class ExternalResourcesManager:
|
|
317
333
|
)
|
318
334
|
self.state_mgr.update_resource_status(key, ResourceStatus.CREATED)
|
319
335
|
|
320
|
-
def _build_external_resource(
|
321
|
-
self, spec: ExternalResourceSpec, er_inventory: ExternalResourcesInventory
|
322
|
-
) -> ExternalResource:
|
336
|
+
def _build_external_resource(self, spec: ExternalResourceSpec) -> ExternalResource:
|
323
337
|
f = self.factories.get_factory(spec.provision_provider)
|
324
338
|
resource = f.create_external_resource(spec)
|
325
339
|
f.validate_external_resource(resource)
|
326
340
|
return resource
|
327
341
|
|
328
|
-
def
|
329
|
-
|
342
|
+
def _find_linked_resources(
|
343
|
+
self, spec: ExternalResourceSpec
|
344
|
+
) -> set[ExternalResourceKey]:
|
345
|
+
f = self.factories.get_factory(spec.provision_provider)
|
346
|
+
return f.find_linked_resources(spec)
|
330
347
|
|
331
348
|
def handle_resources(self) -> None:
|
332
349
|
desired_r = self._get_desired_objects_reconciliations()
|
@@ -355,6 +372,7 @@ class ExternalResourcesManager:
|
|
355
372
|
self._sync_secrets(to_sync_keys=to_sync_keys | pending_sync_keys)
|
356
373
|
|
357
374
|
def handle_dry_run_resources(self) -> None:
|
375
|
+
self._check_orphaned_objects()
|
358
376
|
desired_r = self._get_desired_objects_reconciliations()
|
359
377
|
deleted_r = self._get_deleted_objects_reconciliations()
|
360
378
|
reconciliations = desired_r.union(deleted_r)
|
@@ -3,11 +3,7 @@ import json
|
|
3
3
|
from abc import (
|
4
4
|
ABC,
|
5
5
|
)
|
6
|
-
from collections.abc import
|
7
|
-
Iterable,
|
8
|
-
Iterator,
|
9
|
-
MutableMapping,
|
10
|
-
)
|
6
|
+
from collections.abc import ItemsView, Iterable, Iterator, MutableMapping
|
11
7
|
from enum import StrEnum
|
12
8
|
from typing import Any
|
13
9
|
|
@@ -38,6 +34,17 @@ from reconcile.utils.external_resource_spec import (
|
|
38
34
|
)
|
39
35
|
|
40
36
|
|
37
|
+
class ExternalResourceOrphanedResourcesError(Exception):
|
38
|
+
def __init__(self, orphans: Iterable["ExternalResourceKey"]) -> None:
|
39
|
+
msg = [
|
40
|
+
"There are orphaned resources in the configuration. ",
|
41
|
+
"To delete ERv2 managed external resources, set the 'delete: true' attribute.\n",
|
42
|
+
"Orphans:\n",
|
43
|
+
"\n".join(map(str, orphans)),
|
44
|
+
]
|
45
|
+
super().__init__("".join(msg))
|
46
|
+
|
47
|
+
|
41
48
|
class ExternalResourceValidationError(Exception):
|
42
49
|
errors: list[str] = []
|
43
50
|
|
@@ -82,17 +89,17 @@ class ExternalResourcesInventory(MutableMapping):
|
|
82
89
|
def __init__(self, namespaces: Iterable[NamespaceV1]) -> None:
|
83
90
|
self._inventory: dict[ExternalResourceKey, ExternalResourceSpec] = {}
|
84
91
|
|
85
|
-
|
86
|
-
(
|
92
|
+
resource_providers = [
|
93
|
+
(rp, ns)
|
87
94
|
for ns in namespaces
|
88
|
-
for
|
89
|
-
if isinstance(
|
95
|
+
for rp in ns.external_resources or []
|
96
|
+
if isinstance(rp, SUPPORTED_RESOURCE_PROVIDERS) and rp.resources
|
90
97
|
]
|
91
98
|
|
92
99
|
desired_specs = [
|
93
|
-
self._build_external_resource_spec(ns,
|
94
|
-
for (
|
95
|
-
for r in
|
100
|
+
self._build_external_resource_spec(ns, rp, r)
|
101
|
+
for (rp, ns) in resource_providers
|
102
|
+
for r in rp.resources
|
96
103
|
if isinstance(r, SUPPORTED_RESOURCE_TYPES) and r.managed_by_erv2
|
97
104
|
]
|
98
105
|
|
@@ -136,6 +143,9 @@ class ExternalResourcesInventory(MutableMapping):
|
|
136
143
|
def __len__(self) -> int:
|
137
144
|
return len(self._inventory)
|
138
145
|
|
146
|
+
def items(self) -> ItemsView[ExternalResourceKey, ExternalResourceSpec]:
|
147
|
+
return self._inventory.items()
|
148
|
+
|
139
149
|
def get_inventory_spec(
|
140
150
|
self, provision_provider: str, provisioner: str, provider: str, identifier: str
|
141
151
|
) -> ExternalResourceSpec:
|
@@ -281,6 +291,9 @@ class Reconciliation(BaseModel, frozen=True):
|
|
281
291
|
module_configuration: ExternalResourceModuleConfiguration = (
|
282
292
|
ExternalResourceModuleConfiguration()
|
283
293
|
)
|
294
|
+
# linked_resources store dependants resources. They will get reconciled
|
295
|
+
# every time the parent resource reconciliation finishes.
|
296
|
+
linked_resources: frozenset[ExternalResourceKey] | None
|
284
297
|
|
285
298
|
|
286
299
|
class ReconcileAction(StrEnum):
|
@@ -20,7 +20,9 @@ from reconcile.external_resources.meta import (
|
|
20
20
|
SECRET_UPDATED_AT,
|
21
21
|
SECRET_UPDATED_AT_TIMEFORMAT,
|
22
22
|
)
|
23
|
-
from reconcile.external_resources.model import
|
23
|
+
from reconcile.external_resources.model import (
|
24
|
+
ExternalResourceKey,
|
25
|
+
)
|
24
26
|
from reconcile.openshift_base import ApplyOptions, apply_action
|
25
27
|
from reconcile.typed_queries.clusters_minimal import get_clusters_minimal
|
26
28
|
from reconcile.utils.differ import diff_mappings
|
@@ -207,7 +209,7 @@ class SecretsReconciler:
|
|
207
209
|
If current is newer; don't apply.
|
208
210
|
If other changes; apply and Recycle Pods
|
209
211
|
Desired can not be newer than current.
|
210
|
-
External
|
212
|
+
External resource to Cluster (last reconciliation):
|
211
213
|
If updated_at annotation is the only change; Don't update
|
212
214
|
If other changes; Update Secret and Recycle Pods
|
213
215
|
Current can not be newer then Desired
|
@@ -233,7 +235,7 @@ class SecretsReconciler:
|
|
233
235
|
|
234
236
|
if self.ri.has_error_registered():
|
235
237
|
# Return all specs as error if there are errors.
|
236
|
-
# There is
|
238
|
+
# There is not a clear way to know which specs have failed.
|
237
239
|
return list(specs)
|
238
240
|
else:
|
239
241
|
return []
|
{qontract_reconcile-0.10.1rc1198.dist-info → qontract_reconcile-0.10.1rc1200.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|