qontract-reconcile 0.10.1rc1036__py3-none-any.whl → 0.10.1rc1038__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.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc1036
3
+ Version: 0.10.1rc1038
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
@@ -181,8 +181,8 @@ reconcile/cna/assets/asset_factory.py,sha256=7T7X_J6xIsoGETqBRI45_EyIKEdQcnRPt_G
181
181
  reconcile/cna/assets/null.py,sha256=85mVh97atCoC0aLuX47poTZiyOthmziJeBsUw0c924w,1658
182
182
  reconcile/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
183
  reconcile/dynatrace_token_provider/dependencies.py,sha256=FuRUnK18EyJIIgFwQBZSskIG08mN2VQAcAcaJFTf8zc,2812
184
- reconcile/dynatrace_token_provider/integration.py,sha256=OaRX5B8KiBvXQ57U8dLchlY2pqep5OM1p8HUNJGKGkc,23196
185
- reconcile/dynatrace_token_provider/metrics.py,sha256=xiKkl8fTEBQaXJelGCPNTZhHAWdO1M3pCXNr_Tei63c,1285
184
+ reconcile/dynatrace_token_provider/integration.py,sha256=kECEWCIU_rTX7BeFm85Hjpx76GRm3Y54BFUwxQcLW7E,24682
185
+ reconcile/dynatrace_token_provider/metrics.py,sha256=oP-6NTZENFdvWiS0krnmX6tq3xyOzQ8e6vS0CZWYUuw,1496
186
186
  reconcile/dynatrace_token_provider/model.py,sha256=gkpqo5rRRueBXnIMjp4EEHqBUBuU65TRI8zpdb8GJ0A,241
187
187
  reconcile/dynatrace_token_provider/ocm.py,sha256=iHMsgbsLs-dlrB9UXmWNDF7E4UDe49JOsLa9rnowKfo,4282
188
188
  reconcile/dynatrace_token_provider/validate.py,sha256=40_9QmHoB3-KBc0k_0D4QO00PpNNPS-gU9Z6cIcWga8,1920
@@ -447,7 +447,7 @@ reconcile/saas_auto_promotions_manager/publisher.py,sha256=IZGu-PMffyk3fNL8QcZ2V
447
447
  reconcile/saas_auto_promotions_manager/s3_exporter.py,sha256=IKlVWZmiPnvl7sKeF6JgAlhXZe5CovKTxQc0SNkNSx4,2583
448
448
  reconcile/saas_auto_promotions_manager/subscriber.py,sha256=kIJKT1Xg5FF7EGT5ayK5ROyu_S7FbsYK91WBqrtYjfA,10030
449
449
  reconcile/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
450
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py,sha256=CP392gq0yntzEkqpMJl2j-N4CGfFDFbBfK77J7Oo5Pg,7817
450
+ reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py,sha256=R2CRtjdOggY5lSqt-A5qz2ymqomx4opVeVV_oqBAW0A,7804
451
451
  reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py,sha256=isY8frVsL3PlcdZmdZ4O0qyp76oczl4DUMX9uMArs5Y,1222
452
452
  reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request.py,sha256=BeAJWLow7b4HQyZ9zz398sQkPeIz8chpMkCts2NU27c,1282
453
453
  reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py,sha256=-zWK-cqr_8o9ZEnNfD3cfkv3hrrU4HJ4UMzi4J2Hjhw,6223
@@ -867,8 +867,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
867
867
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
868
868
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
869
869
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
870
- qontract_reconcile-0.10.1rc1036.dist-info/METADATA,sha256=ktF4TYAZVpjXuuOeLeuVYjfer0sgF70DsmjPpSkZ26Y,2213
871
- qontract_reconcile-0.10.1rc1036.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
872
- qontract_reconcile-0.10.1rc1036.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
873
- qontract_reconcile-0.10.1rc1036.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
874
- qontract_reconcile-0.10.1rc1036.dist-info/RECORD,,
870
+ qontract_reconcile-0.10.1rc1038.dist-info/METADATA,sha256=GKt0eKtaXZaF1JTo6RGwQ5MhvxO9N9wMH69a2Z3Th2o,2213
871
+ qontract_reconcile-0.10.1rc1038.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
872
+ qontract_reconcile-0.10.1rc1038.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
873
+ qontract_reconcile-0.10.1rc1038.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
874
+ qontract_reconcile-0.10.1rc1038.dist-info/RECORD,,
@@ -1,14 +1,17 @@
1
1
  import base64
2
2
  import hashlib
3
3
  import logging
4
+ from collections import Counter, defaultdict
4
5
  from collections.abc import Iterable, Mapping, MutableMapping
5
6
  from datetime import timedelta
7
+ from threading import Lock
6
8
  from typing import Any
7
9
 
8
10
  from reconcile.dynatrace_token_provider.dependencies import Dependencies
9
11
  from reconcile.dynatrace_token_provider.metrics import (
10
12
  DTPClustersManagedGauge,
11
13
  DTPOrganizationErrorRate,
14
+ DTPTokensManagedGauge,
12
15
  )
13
16
  from reconcile.dynatrace_token_provider.model import DynatraceAPIToken, K8sSecret
14
17
  from reconcile.dynatrace_token_provider.ocm import (
@@ -56,6 +59,11 @@ class ReconcileErrorSummary(Exception):
56
59
  class DynatraceTokenProviderIntegration(
57
60
  QontractReconcileIntegration[DynatraceTokenProviderIntegrationParams]
58
61
  ):
62
+ def __init__(self, params: DynatraceTokenProviderIntegrationParams) -> None:
63
+ super().__init__(params=params)
64
+ self._lock = Lock()
65
+ self._managed_tokens_cnt: dict[str, Counter[str]] = defaultdict(Counter)
66
+
59
67
  @property
60
68
  def name(self) -> str:
61
69
  return QONTRACT_INTEGRATION
@@ -70,6 +78,22 @@ class DynatraceTokenProviderIntegration(
70
78
  dependencies.populate_all()
71
79
  self.reconcile(dry_run=dry_run, dependencies=dependencies)
72
80
 
81
+ def _token_cnt(self, dt_tenant_id: str, ocm_env_name: str) -> None:
82
+ with self._lock:
83
+ self._managed_tokens_cnt[ocm_env_name][dt_tenant_id] += 1
84
+
85
+ def _expose_token_metrics(self) -> None:
86
+ for ocm_env_name, counter_by_tenant_id in self._managed_tokens_cnt.items():
87
+ for dt_tenant_id, cnt in counter_by_tenant_id.items():
88
+ metrics.set_gauge(
89
+ DTPTokensManagedGauge(
90
+ integration=self.name,
91
+ ocm_env=ocm_env_name,
92
+ dt_tenant_id=dt_tenant_id,
93
+ ),
94
+ cnt,
95
+ )
96
+
73
97
  def reconcile(self, dry_run: bool, dependencies: Dependencies) -> None:
74
98
  token_specs = list(dependencies.token_spec_by_name.values())
75
99
  validate_token_specs(specs=token_specs)
@@ -86,13 +110,6 @@ class DynatraceTokenProviderIntegration(
86
110
  )
87
111
  except Exception as e:
88
112
  unhandled_exceptions.append(f"{ocm_env_name}: {e}")
89
- metrics.set_gauge(
90
- DTPClustersManagedGauge(
91
- integration=self.name,
92
- ocm_env=ocm_env_name,
93
- ),
94
- len(clusters),
95
- )
96
113
  if not clusters:
97
114
  continue
98
115
  if self.params.ocm_organization_ids:
@@ -101,8 +118,16 @@ class DynatraceTokenProviderIntegration(
101
118
  for cluster in clusters
102
119
  if cluster.organization_id in self.params.ocm_organization_ids
103
120
  ]
121
+
104
122
  existing_dtp_tokens: dict[str, dict[str, str]] = {}
105
123
 
124
+ metrics.set_gauge(
125
+ DTPClustersManagedGauge(
126
+ integration=self.name,
127
+ ocm_env=ocm_env_name,
128
+ ),
129
+ len(clusters),
130
+ )
106
131
  for cluster in clusters:
107
132
  try:
108
133
  with DTPOrganizationErrorRate(
@@ -162,11 +187,13 @@ class DynatraceTokenProviderIntegration(
162
187
  existing_dtp_tokens=existing_dtp_tokens[tenant_id],
163
188
  tenant_id=tenant_id,
164
189
  token_spec=token_spec,
190
+ ocm_env_name=ocm_env_name,
165
191
  )
166
192
  except Exception as e:
167
193
  unhandled_exceptions.append(
168
194
  f"{ocm_env_name}/{cluster.organization_id}/{cluster.external_id}: {e}"
169
195
  )
196
+ self._expose_token_metrics()
170
197
 
171
198
  if unhandled_exceptions:
172
199
  raise ReconcileErrorSummary(unhandled_exceptions)
@@ -180,6 +207,7 @@ class DynatraceTokenProviderIntegration(
180
207
  existing_dtp_tokens: MutableMapping[str, str],
181
208
  tenant_id: str,
182
209
  token_spec: DynatraceTokenProviderTokenSpecV1,
210
+ ocm_env_name: str,
183
211
  ) -> None:
184
212
  if cluster.organization_id not in token_spec.ocm_org_ids:
185
213
  logging.info(
@@ -247,6 +275,8 @@ class DynatraceTokenProviderIntegration(
247
275
  existing_dtp_tokens=existing_dtp_tokens,
248
276
  dt_client=dt_client,
249
277
  cluster_uuid=cluster.external_id,
278
+ dt_tenant_id=tenant_id,
279
+ ocm_env_name=ocm_env_name,
250
280
  )
251
281
  if has_diff:
252
282
  if not dry_run:
@@ -302,6 +332,8 @@ class DynatraceTokenProviderIntegration(
302
332
  cluster_uuid: str,
303
333
  dt_client: DynatraceClient,
304
334
  token_name_in_dt_api: str,
335
+ ocm_env_name: str,
336
+ dt_tenant_id: str,
305
337
  dry_run: bool,
306
338
  ) -> None:
307
339
  """
@@ -311,6 +343,7 @@ class DynatraceTokenProviderIntegration(
311
343
  A list query on the tokens does not return each tokens configuration.
312
344
  We encode the token configuration in the token name to save API calls.
313
345
  """
346
+ self._token_cnt(dt_tenant_id=dt_tenant_id, ocm_env_name=ocm_env_name)
314
347
  expected_name = self.dynatrace_token_name(spec=spec, cluster_uuid=cluster_uuid)
315
348
  if token_name_in_dt_api != expected_name:
316
349
  logging.info(
@@ -329,6 +362,8 @@ class DynatraceTokenProviderIntegration(
329
362
  existing_dtp_tokens: MutableMapping[str, str],
330
363
  dt_client: DynatraceClient,
331
364
  cluster_uuid: str,
365
+ ocm_env_name: str,
366
+ dt_tenant_id: str,
332
367
  ) -> tuple[bool, Iterable[K8sSecret]]:
333
368
  has_diff = False
334
369
  desired: list[K8sSecret] = []
@@ -362,6 +397,8 @@ class DynatraceTokenProviderIntegration(
362
397
  dt_client=dt_client,
363
398
  dry_run=dry_run,
364
399
  token_name_in_dt_api=existing_dtp_tokens[cur_token.id],
400
+ dt_tenant_id=dt_tenant_id,
401
+ ocm_env_name=ocm_env_name,
365
402
  )
366
403
  desired_tokens.append(cur_token)
367
404
  desired.append(
@@ -50,3 +50,13 @@ class DTPClustersManagedGauge(DTPBaseMetric, GaugeMetric):
50
50
  @classmethod
51
51
  def name(cls) -> str:
52
52
  return "dtp_clusters_managed"
53
+
54
+
55
+ class DTPTokensManagedGauge(DTPBaseMetric, GaugeMetric):
56
+ "Gauge for the number of tokens DTP manages"
57
+
58
+ dt_tenant_id: str
59
+
60
+ @classmethod
61
+ def name(cls) -> str:
62
+ return "dtp_tokens_managed"
@@ -8,7 +8,7 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.open_merge_req
8
8
 
9
9
 
10
10
  class Reason(Enum):
11
- MISSING_UNBATCHING = "Closing this MR because it failed MR check and isn't marked as un-batchable yet. cc @kfischer"
11
+ MISSING_UNBATCHING = "Closing this MR because it failed MR check and isn't marked as un-batchable yet."
12
12
  OUTDATED_CONTENT = "Closing this MR because it has out-dated content."
13
13
  NEW_BATCH = "Closing this MR in favor of a new batch MR."
14
14