qontract-reconcile 0.10.2.dev94__py3-none-any.whl → 0.10.2.dev96__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev94
3
+ Version: 0.10.2.dev96
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
@@ -207,11 +207,11 @@ reconcile/external_resources/reconciler.py,sha256=-0trp1K-iUgOQn3mm1ZUSmfaReRrUT
207
207
  reconcile/external_resources/secrets_sync.py,sha256=ZDxzGZ6wC4zxLhA7-L39xDRH6rzUM285gytuzmRQdlw,16208
208
208
  reconcile/external_resources/state.py,sha256=gF3ACdl7YiUlbQ4uEGrD6i_Txxqr6mT9f8IFlTQ-8dY,13176
209
209
  reconcile/fleet_labeler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
210
- reconcile/fleet_labeler/dependencies.py,sha256=ZOpmtwgxEPBWU2yHRc6rhPwlvqhwYSsNMJQ_jVq1dLI,2993
211
- reconcile/fleet_labeler/integration.py,sha256=IeDUDlIIZREQRbsODB9xsCMoNrMk5738OF_fP7lUGFs,13128
210
+ reconcile/fleet_labeler/dependencies.py,sha256=6vD9dC1pXOztWQpQCZa2ZLbXrTf50kzjtpqewRybuJ4,3169
211
+ reconcile/fleet_labeler/integration.py,sha256=vMvDnQW1NXv2qWeG8ab_gguBq45UtmYErSXy6XR83d8,14149
212
212
  reconcile/fleet_labeler/merge_request.py,sha256=SfGxXInxeJzVnsTtO0ZC9-PesUJMdpKxKY9eCB6ms-g,1538
213
213
  reconcile/fleet_labeler/meta.py,sha256=lWnpH2U0PHCPXu9Ok_CPmO494qQJQ5pOuqo28s0jzIQ,146
214
- reconcile/fleet_labeler/metrics.py,sha256=wx9BmXLsN67m-aSsf81iB7Ehj5SzUsS2WB75isUReZg,662
214
+ reconcile/fleet_labeler/metrics.py,sha256=zhcp06woGaZywTqWZf3znh6C2S2u7OHBLXalXYKuTzQ,1934
215
215
  reconcile/fleet_labeler/ocm.py,sha256=qcg1_p7nKlZG7-MQeOZos3rz6YSPAPh-HKxE3OVJwe0,4165
216
216
  reconcile/fleet_labeler/validate.py,sha256=gzc2tt7h9F60h7dcyJfEmsnjnfuux5Jtc_WzrIqr-5k,2541
217
217
  reconcile/fleet_labeler/vcs.py,sha256=6UHUQ08AGAHXF7629I6X-T_E1pvx96LxjS66EeOzve4,1108
@@ -224,7 +224,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=BgMx-NyV9mTuv7Sotb2OioC
224
224
  reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
225
225
  reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
226
226
  reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
227
- reconcile/gql_definitions/introspection.json,sha256=nBoWZM_ilrKlbCUF9cbRe7D1jsTqHqfGkLQW2gbleBM,2239254
227
+ reconcile/gql_definitions/introspection.json,sha256=xA_cHhSy0wr9PG9y_Nwk75MbnjtHQjOEMd48nLZMK8E,2239784
228
228
  reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
229
229
  reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
230
230
  reconcile/gql_definitions/acs/acs_policies.py,sha256=bN5i4mks10Z23KJSj7jqp966Osq2dps4d-sPH9gjxEA,7008
@@ -314,7 +314,7 @@ reconcile/gql_definitions/external_resources/external_resources_settings.py,sha2
314
314
  reconcile/gql_definitions/external_resources/fragments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
315
315
  reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py,sha256=T_qWCRtzU8F9frebBXG9TkeQdrKGt3R9YinSngPoFqM,1262
316
316
  reconcile/gql_definitions/fleet_labeler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
317
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py,sha256=rII_VzEfjGibY1lJXMBMKdCeV7kaNyRXk9-J9-neBoU,4412
317
+ reconcile/gql_definitions/fleet_labeler/fleet_labels.py,sha256=ow9LTm376Y5rCVMWgRtrj2yWKK7_aBC5AM7svLN7pKo,4546
318
318
  reconcile/gql_definitions/fragments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
319
319
  reconcile/gql_definitions/fragments/aus_organization.py,sha256=uBKbTuBa3CZmTXR5HOcGhRcu2U9kM93KbYmoWTxcpB0,4767
320
320
  reconcile/gql_definitions/fragments/aws_account_common.py,sha256=3-7ZAP6GSff7Z2Syz2VQCLY4IySqBOSVmceaRiVNQpw,2385
@@ -786,7 +786,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
786
786
  tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
787
787
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
788
788
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
789
- qontract_reconcile-0.10.2.dev94.dist-info/METADATA,sha256=6jF1IpkimS99Wf-hXeOV8tYFGl0GGQgVl_p9Ax-YDG4,24565
790
- qontract_reconcile-0.10.2.dev94.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
791
- qontract_reconcile-0.10.2.dev94.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
792
- qontract_reconcile-0.10.2.dev94.dist-info/RECORD,,
789
+ qontract_reconcile-0.10.2.dev96.dist-info/METADATA,sha256=HAWau-mbdGSxEIuXiVqfR00bMYmkHZPCrQn2jcTzmmU,24565
790
+ qontract_reconcile-0.10.2.dev96.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
791
+ qontract_reconcile-0.10.2.dev96.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
792
+ qontract_reconcile-0.10.2.dev96.dist-info/RECORD,,
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections.abc import Mapping
4
4
 
5
+ from reconcile.fleet_labeler.metrics import FleetLabelerMetrics
5
6
  from reconcile.fleet_labeler.ocm import OCMClient, OCMClientConfig
6
7
  from reconcile.fleet_labeler.vcs import VCS
7
8
  from reconcile.gql_definitions.fleet_labeler.fleet_labels import FleetLabelsSpecV1
@@ -26,12 +27,14 @@ class Dependencies:
26
27
  self,
27
28
  label_specs_by_name: Mapping[str, FleetLabelsSpecV1],
28
29
  ocm_clients_by_label_spec_name: Mapping[str, OCMClient],
30
+ metrics: FleetLabelerMetrics,
29
31
  vcs: VCS,
30
32
  dry_run: bool,
31
33
  ):
32
34
  self.label_specs_by_name = label_specs_by_name
33
35
  self.ocm_clients_by_label_spec_name = ocm_clients_by_label_spec_name
34
36
  self.vcs = vcs
37
+ self.metrics = metrics
35
38
  self.dry_run = dry_run
36
39
 
37
40
  @classmethod
@@ -45,6 +48,7 @@ class Dependencies:
45
48
  ocm_clients_by_label_spec_name=_ocm_clients(secret_reader=secret_reader),
46
49
  vcs=_vcs(secret_reader=secret_reader, dry_run=dry_run),
47
50
  dry_run=dry_run,
51
+ metrics=FleetLabelerMetrics(),
48
52
  )
49
53
 
50
54
 
@@ -13,7 +13,9 @@ from reconcile.fleet_labeler.meta import (
13
13
  QONTRACT_INTEGRATION,
14
14
  QONTRACT_INTEGRATION_VERSION,
15
15
  )
16
- from reconcile.fleet_labeler.metrics import FleetLabelerDuplicateClusterMatchesGauge
16
+ from reconcile.fleet_labeler.metrics import (
17
+ FleetLabelerMetrics,
18
+ )
17
19
  from reconcile.fleet_labeler.ocm import OCMClient
18
20
  from reconcile.fleet_labeler.validate import validate_label_specs
19
21
  from reconcile.fleet_labeler.vcs import VCS, Gitlab404Error
@@ -23,9 +25,6 @@ from reconcile.gql_definitions.fleet_labeler.fleet_labels import (
23
25
  FleetSubscriptionLabelTemplateV1,
24
26
  )
25
27
  from reconcile.typed_queries.fleet_labels import get_fleet_label_specs
26
- from reconcile.utils import (
27
- metrics,
28
- )
29
28
  from reconcile.utils.differ import diff_mappings
30
29
  from reconcile.utils.jinja2.utils import process_jinja2_template
31
30
  from reconcile.utils.ruamel import create_ruamel_instance
@@ -67,6 +66,7 @@ class FleetLabelerIntegration(QontractReconcileIntegration[NoParams]):
67
66
  secret_reader=self.secret_reader,
68
67
  dry_run=dry_run,
69
68
  )
69
+ self._metrics = dependencies.metrics
70
70
  self.reconcile(dependencies=dependencies)
71
71
 
72
72
  def reconcile(self, dependencies: Dependencies) -> None:
@@ -89,13 +89,15 @@ class FleetLabelerIntegration(QontractReconcileIntegration[NoParams]):
89
89
  vcs=dependencies.vcs,
90
90
  all_desired_clusters=all_desired_clusters,
91
91
  clusters_with_duplicate_matches=clusters_with_duplicate_matches,
92
+ metrics=dependencies.metrics,
92
93
  dry_run=dependencies.dry_run,
93
94
  )
95
+ synch_labels = spec.dry_run_label_synchronization or dependencies.dry_run
94
96
  self._sync_subscription_labels(
95
97
  spec=spec,
96
98
  desired_clusters=all_desired_clusters,
97
99
  ocm=ocm,
98
- dry_run=dependencies.dry_run,
100
+ dry_run=synch_labels,
99
101
  )
100
102
 
101
103
  def _discover_desired_clusters(
@@ -243,6 +245,7 @@ class FleetLabelerIntegration(QontractReconcileIntegration[NoParams]):
243
245
  vcs: VCS,
244
246
  clusters_with_duplicate_matches: dict[str, list[ClusterData]],
245
247
  all_desired_clusters: dict[str, ClusterData],
248
+ metrics: FleetLabelerMetrics,
246
249
  dry_run: bool,
247
250
  ) -> None:
248
251
  all_current_cluster_ids = {cluster.cluster_id for cluster in spec.clusters}
@@ -253,28 +256,46 @@ class FleetLabelerIntegration(QontractReconcileIntegration[NoParams]):
253
256
  logging.error(
254
257
  f"[{spec.name}] Cluster ID {cluster_id} is matched multiple times by different label matchers:\n{label_matches}"
255
258
  )
256
- metrics.set_gauge(
257
- FleetLabelerDuplicateClusterMatchesGauge(
258
- integration=self.name,
259
- ocm_name=spec.ocm.name,
260
- ),
261
- len(clusters_with_duplicate_matches),
259
+ metrics.set_duplicate_cluster_matches_gauge(
260
+ ocm_name=spec.ocm.name,
261
+ spec_name=spec.name,
262
+ value=len(clusters_with_duplicate_matches),
262
263
  )
263
264
 
264
- clusters_to_add = [
265
- YamlCluster(
266
- cluster_id=cluster_id,
267
- subscription_id=cluster_info.subscription_id,
268
- name=cluster_info.name,
269
- server_url=cluster_info.server_url,
270
- subscription_labels_content=self._render_default_labels(
265
+ clusters_to_add: list[YamlCluster] = []
266
+ label_rendering_errors_cnt = 0
267
+ for cluster_id, cluster_info in all_desired_clusters.items():
268
+ if cluster_id in all_current_cluster_ids:
269
+ continue
270
+ try:
271
+ default_labels = self._render_default_labels(
271
272
  template=cluster_info.desired_label_default.subscription_label_template,
272
273
  labels=ocm.get_cluster_labels(cluster_id=cluster_id),
273
- ),
274
- )
275
- for cluster_id, cluster_info in all_desired_clusters.items()
276
- if cluster_id not in all_current_cluster_ids
277
- ]
274
+ )
275
+ except Exception as e:
276
+ logging.error(
277
+ f"[{spec.name}] Error while rendering default labels for {cluster_id=} {cluster_info.subscription_id=} - skipping cluster: {e}"
278
+ )
279
+ default_labels = None
280
+ label_rendering_errors_cnt += 1
281
+
282
+ if default_labels:
283
+ # Note, we are skipping this cluster if there are no default_labels rendered
284
+ clusters_to_add.append(
285
+ YamlCluster(
286
+ cluster_id=cluster_id,
287
+ subscription_id=cluster_info.subscription_id,
288
+ name=cluster_info.name,
289
+ server_url=cluster_info.server_url,
290
+ subscription_labels_content=default_labels,
291
+ )
292
+ )
293
+ metrics.set_label_rendering_error_gauge(
294
+ ocm_name=spec.ocm.name,
295
+ spec_name=spec.name,
296
+ value=label_rendering_errors_cnt,
297
+ )
298
+
278
299
  cluster_ids_to_delete = all_current_cluster_ids - all_desired_clusters.keys()
279
300
 
280
301
  if not (cluster_ids_to_delete or clusters_to_add):
@@ -282,7 +303,7 @@ class FleetLabelerIntegration(QontractReconcileIntegration[NoParams]):
282
303
 
283
304
  for yaml_cluster in clusters_to_add:
284
305
  logging.info(
285
- f"[{spec.name}] Adding cluster '{yaml_cluster.name}' with id '{yaml_cluster.cluster_id}' to inventory with default labels {yaml_cluster.subscription_labels_content}."
306
+ f"[{spec.name}] Adding cluster '{yaml_cluster.name}' with id '{yaml_cluster.cluster_id}' and subscription id '{yaml_cluster.subscription_id}' to inventory with default labels {yaml_cluster.subscription_labels_content}."
286
307
  )
287
308
  for cluster_id in cluster_ids_to_delete:
288
309
  logging.info(
@@ -1,13 +1,46 @@
1
1
  from pydantic import BaseModel
2
2
 
3
+ from reconcile.fleet_labeler.meta import QONTRACT_INTEGRATION
4
+ from reconcile.utils import (
5
+ metrics,
6
+ )
3
7
  from reconcile.utils.metrics import (
4
8
  GaugeMetric,
5
9
  )
6
10
 
7
11
 
12
+ class FleetLabelerMetrics:
13
+ """
14
+ Thin OOP wrapper for tests
15
+ """
16
+
17
+ def set_label_rendering_error_gauge(
18
+ self, ocm_name: str, spec_name: str, value: int
19
+ ) -> None:
20
+ metrics.set_gauge(
21
+ FleetLabelerDuplicateClusterMatchesGauge(
22
+ ocm_name=ocm_name,
23
+ spec=spec_name,
24
+ ),
25
+ value,
26
+ )
27
+
28
+ def set_duplicate_cluster_matches_gauge(
29
+ self, ocm_name: str, spec_name: str, value: int
30
+ ) -> None:
31
+ metrics.set_gauge(
32
+ FleetLabelerLabelRenderingErrorGauge(
33
+ ocm_name=ocm_name,
34
+ spec=spec_name,
35
+ ),
36
+ value,
37
+ )
38
+
39
+
8
40
  class FleetLabelerBaseMetric(BaseModel):
9
- integration: str
41
+ integration: str = QONTRACT_INTEGRATION
10
42
  ocm_name: str
43
+ spec: str
11
44
 
12
45
 
13
46
  class FleetLabelerDuplicateClusterMatchesGauge(FleetLabelerBaseMetric, GaugeMetric):
@@ -21,3 +54,15 @@ class FleetLabelerDuplicateClusterMatchesGauge(FleetLabelerBaseMetric, GaugeMetr
21
54
  @classmethod
22
55
  def name(cls) -> str:
23
56
  return "fleet_labeler_duplicate_cluster_matches"
57
+
58
+
59
+ class FleetLabelerLabelRenderingErrorGauge(FleetLabelerBaseMetric, GaugeMetric):
60
+ """
61
+ Gauge for the number of clusters that have label render errors. This
62
+ happens when the fleet labeler is unable to render the subscription labels
63
+ template for a cluster. Check the logs to identify the clusters with label render errors.
64
+ """
65
+
66
+ @classmethod
67
+ def name(cls) -> str:
68
+ return "fleet_labeler_label_rendering_error"
@@ -33,6 +33,7 @@ query FleetLabelSpecs {
33
33
  name
34
34
  path
35
35
  managedSubscriptionLabelPrefix
36
+ dryRunLabelSynchronization
36
37
  ocm {
37
38
  name
38
39
  environment {
@@ -113,6 +114,7 @@ class FleetLabelsSpecV1(ConfiguredBaseModel):
113
114
  name: str = Field(..., alias="name")
114
115
  path: str = Field(..., alias="path")
115
116
  managed_subscription_label_prefix: str = Field(..., alias="managedSubscriptionLabelPrefix")
117
+ dry_run_label_synchronization: Optional[bool] = Field(..., alias="dryRunLabelSynchronization")
116
118
  ocm: OpenShiftClusterManagerV1 = Field(..., alias="ocm")
117
119
  label_defaults: list[FleetLabelDefaultV1] = Field(..., alias="labelDefaults")
118
120
  clusters: list[FleetClusterV1] = Field(..., alias="clusters")
@@ -34397,6 +34397,18 @@
34397
34397
  "isDeprecated": false,
34398
34398
  "deprecationReason": null
34399
34399
  },
34400
+ {
34401
+ "name": "dryRunLabelSynchronization",
34402
+ "description": null,
34403
+ "args": [],
34404
+ "type": {
34405
+ "kind": "SCALAR",
34406
+ "name": "Boolean",
34407
+ "ofType": null
34408
+ },
34409
+ "isDeprecated": false,
34410
+ "deprecationReason": null
34411
+ },
34400
34412
  {
34401
34413
  "name": "managedSubscriptionLabelPrefix",
34402
34414
  "description": null,