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.
- {qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.dist-info}/RECORD +8 -8
- reconcile/dynatrace_token_provider/integration.py +44 -7
- reconcile/dynatrace_token_provider/metrics.py +10 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -1
- {qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.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.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
|
{qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.dist-info}/RECORD
RENAMED
@@ -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=
|
185
|
-
reconcile/dynatrace_token_provider/metrics.py,sha256=
|
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=
|
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.
|
871
|
-
qontract_reconcile-0.10.
|
872
|
-
qontract_reconcile-0.10.
|
873
|
-
qontract_reconcile-0.10.
|
874
|
-
qontract_reconcile-0.10.
|
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.
|
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
|
|
{qontract_reconcile-0.10.1rc1036.dist-info → qontract_reconcile-0.10.1rc1038.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|