qontract-reconcile 0.10.2.dev91__py3-none-any.whl → 0.10.2.dev93__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.dev91.dist-info → qontract_reconcile-0.10.2.dev93.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev91.dist-info → qontract_reconcile-0.10.2.dev93.dist-info}/RECORD +8 -8
- reconcile/dynatrace_token_provider/integration.py +10 -12
- reconcile/dynatrace_token_provider/ocm.py +11 -2
- reconcile/fleet_labeler/integration.py +6 -2
- reconcile/fleet_labeler/ocm.py +20 -5
- {qontract_reconcile-0.10.2.dev91.dist-info → qontract_reconcile-0.10.2.dev93.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev91.dist-info → qontract_reconcile-0.10.2.dev93.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev91.dist-info → qontract_reconcile-0.10.2.dev93.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.dev93
|
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.dev91.dist-info → qontract_reconcile-0.10.2.dev93.dist-info}/RECORD
RENAMED
@@ -185,10 +185,10 @@ reconcile/cna/assets/asset_factory.py,sha256=7T7X_J6xIsoGETqBRI45_EyIKEdQcnRPt_G
|
|
185
185
|
reconcile/cna/assets/null.py,sha256=85mVh97atCoC0aLuX47poTZiyOthmziJeBsUw0c924w,1658
|
186
186
|
reconcile/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
187
187
|
reconcile/dynatrace_token_provider/dependencies.py,sha256=FuRUnK18EyJIIgFwQBZSskIG08mN2VQAcAcaJFTf8zc,2812
|
188
|
-
reconcile/dynatrace_token_provider/integration.py,sha256=
|
188
|
+
reconcile/dynatrace_token_provider/integration.py,sha256=ysPto7wPZW_t3KFXyWOxRNQT140Q4OOe3Eu4BX0p6Uo,26505
|
189
189
|
reconcile/dynatrace_token_provider/metrics.py,sha256=oP-6NTZENFdvWiS0krnmX6tq3xyOzQ8e6vS0CZWYUuw,1496
|
190
190
|
reconcile/dynatrace_token_provider/model.py,sha256=gkpqo5rRRueBXnIMjp4EEHqBUBuU65TRI8zpdb8GJ0A,241
|
191
|
-
reconcile/dynatrace_token_provider/ocm.py,sha256=
|
191
|
+
reconcile/dynatrace_token_provider/ocm.py,sha256=7P0AoyAhAmvH9ffKMEE3HB9sCmWvrwYcSBscsVt5964,4729
|
192
192
|
reconcile/dynatrace_token_provider/validate.py,sha256=40_9QmHoB3-KBc0k_0D4QO00PpNNPS-gU9Z6cIcWga8,1920
|
193
193
|
reconcile/endpoints_discovery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
194
194
|
reconcile/endpoints_discovery/integration.py,sha256=ecjIZK_h6JO2wUhUmJlZ9pjOh60nS5aenEWGDj6YJdw,14790
|
@@ -208,11 +208,11 @@ reconcile/external_resources/secrets_sync.py,sha256=ZDxzGZ6wC4zxLhA7-L39xDRH6rzU
|
|
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
210
|
reconcile/fleet_labeler/dependencies.py,sha256=ZOpmtwgxEPBWU2yHRc6rhPwlvqhwYSsNMJQ_jVq1dLI,2993
|
211
|
-
reconcile/fleet_labeler/integration.py,sha256=
|
211
|
+
reconcile/fleet_labeler/integration.py,sha256=IeDUDlIIZREQRbsODB9xsCMoNrMk5738OF_fP7lUGFs,13128
|
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
214
|
reconcile/fleet_labeler/metrics.py,sha256=wx9BmXLsN67m-aSsf81iB7Ehj5SzUsS2WB75isUReZg,662
|
215
|
-
reconcile/fleet_labeler/ocm.py,sha256=
|
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
|
218
218
|
reconcile/glitchtip/README.md,sha256=rfXT6jNP9khJW65jL7I2PgoxvxgcGGuJF8NpbzufEQ4,4335
|
@@ -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.
|
790
|
-
qontract_reconcile-0.10.2.
|
791
|
-
qontract_reconcile-0.10.2.
|
792
|
-
qontract_reconcile-0.10.2.
|
789
|
+
qontract_reconcile-0.10.2.dev93.dist-info/METADATA,sha256=OCfp9-cXH8VsKHhK1x5598Kh2bXedhZ9huHZ0qp59U8,24565
|
790
|
+
qontract_reconcile-0.10.2.dev93.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
791
|
+
qontract_reconcile-0.10.2.dev93.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
792
|
+
qontract_reconcile-0.10.2.dev93.dist-info/RECORD,,
|
@@ -117,14 +117,14 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
117
117
|
token_spec = token_spec_by_name.get(cluster.token_spec_name)
|
118
118
|
if not token_spec:
|
119
119
|
logging.debug(
|
120
|
-
f"[{cluster.
|
120
|
+
f"[{cluster.id=}] Skipping cluster. {cluster.token_spec_name=} does not exist."
|
121
121
|
)
|
122
122
|
continue
|
123
123
|
if cluster.organization_id in token_spec.ocm_org_ids:
|
124
124
|
filtered_clusters.append(cluster)
|
125
125
|
else:
|
126
126
|
logging.debug(
|
127
|
-
f"[{cluster.
|
127
|
+
f"[{cluster.id=}] Skipping cluster for {token_spec.name=}. {cluster.organization_id=} is not defined in {token_spec.ocm_org_ids=}."
|
128
128
|
)
|
129
129
|
return filtered_clusters
|
130
130
|
|
@@ -175,7 +175,7 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
175
175
|
error=f"Missing label {DTP_TENANT_LABEL}",
|
176
176
|
)
|
177
177
|
logging.warn(
|
178
|
-
f"[{cluster.
|
178
|
+
f"[{cluster.id=}] Missing value for label {DTP_TENANT_LABEL}"
|
179
179
|
)
|
180
180
|
continue
|
181
181
|
if (
|
@@ -188,7 +188,7 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
188
188
|
error=f"Dynatrace tenant {tenant_id} does not exist",
|
189
189
|
)
|
190
190
|
logging.warn(
|
191
|
-
f"[{cluster.
|
191
|
+
f"[{cluster.id=}] Dynatrace {tenant_id=} does not exist"
|
192
192
|
)
|
193
193
|
continue
|
194
194
|
dt_client = dependencies.dynatrace_client_by_tenant_id[
|
@@ -205,7 +205,7 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
205
205
|
error=f"Token spec {cluster.token_spec_name} does not exist",
|
206
206
|
)
|
207
207
|
logging.warn(
|
208
|
-
f"[{cluster.
|
208
|
+
f"[{cluster.id=}] Token spec '{cluster.token_spec_name}' does not exist"
|
209
209
|
)
|
210
210
|
continue
|
211
211
|
if tenant_id not in existing_dtp_tokens:
|
@@ -232,7 +232,7 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
232
232
|
)
|
233
233
|
except Exception as e:
|
234
234
|
unhandled_exceptions.append(
|
235
|
-
f"{ocm_env_name}/{cluster.organization_id}/{cluster.
|
235
|
+
f"{ocm_env_name}/{cluster.organization_id}/{cluster.id}: {e}"
|
236
236
|
)
|
237
237
|
self._expose_token_metrics()
|
238
238
|
|
@@ -289,11 +289,9 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
289
289
|
f"DTP can't create {token_spec.name=} {e.args!s}",
|
290
290
|
)
|
291
291
|
logging.info(
|
292
|
-
f"{token_spec.name=} created in {dt_api_url} for {cluster.
|
293
|
-
)
|
294
|
-
logging.info(
|
295
|
-
f"{SYNCSET_AND_MANIFEST_ID} created for {cluster.external_id=}."
|
292
|
+
f"{token_spec.name=} created in {dt_api_url} for {cluster.id=}."
|
296
293
|
)
|
294
|
+
logging.info(f"{SYNCSET_AND_MANIFEST_ID} created for {cluster.id=}.")
|
297
295
|
else:
|
298
296
|
current_k8s_secrets: list[K8sSecret] = []
|
299
297
|
if cluster.is_hcp:
|
@@ -344,7 +342,7 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
344
342
|
f"DTP can't patch {token_spec.name=} for {SYNCSET_AND_MANIFEST_ID} due to {e.args!s}",
|
345
343
|
)
|
346
344
|
logging.info(
|
347
|
-
f"Patched {token_spec.name=} for {SYNCSET_AND_MANIFEST_ID} in {cluster.
|
345
|
+
f"Patched {token_spec.name=} for {SYNCSET_AND_MANIFEST_ID} in {cluster.id=}."
|
348
346
|
)
|
349
347
|
|
350
348
|
def scopes_hash(self, scopes: Iterable[str], length: int) -> str:
|
@@ -425,7 +423,7 @@ class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
|
425
423
|
dt_client, cluster_uuid, desired_token
|
426
424
|
)
|
427
425
|
existing_dtp_tokens[cur_token.id] = cur_token.name
|
428
|
-
if cur_token:
|
426
|
+
if cur_token and cur_token.id in existing_dtp_tokens:
|
429
427
|
self.sync_token_in_dynatrace(
|
430
428
|
token_id=cur_token.id,
|
431
429
|
spec=desired_token,
|
@@ -38,6 +38,9 @@ DTP_TENANT_LABEL = sre_capability_label_key("dtp", "tenant")
|
|
38
38
|
DTP_SPEC_LABEL = sre_capability_label_key("dtp", "token-spec")
|
39
39
|
DTP_LABEL_SEARCH = sre_capability_label_key("dtp", "%")
|
40
40
|
|
41
|
+
DTP_TENANT_V2_LABEL = sre_capability_label_key("dtp.v2", "tenant")
|
42
|
+
DTP_SPEC_V2_LABEL = sre_capability_label_key("dtp.v2", "token-spec")
|
43
|
+
|
41
44
|
|
42
45
|
class Cluster(BaseModel):
|
43
46
|
id: str
|
@@ -49,8 +52,14 @@ class Cluster(BaseModel):
|
|
49
52
|
|
50
53
|
@staticmethod
|
51
54
|
def from_cluster_details(cluster: ClusterDetails) -> Cluster:
|
52
|
-
dt_tenant = cluster.labels.get_label_value(
|
53
|
-
token_spec_name = cluster.labels.get_label_value(
|
55
|
+
dt_tenant = cluster.labels.get_label_value(DTP_TENANT_V2_LABEL)
|
56
|
+
token_spec_name = cluster.labels.get_label_value(DTP_SPEC_V2_LABEL)
|
57
|
+
|
58
|
+
# TODO: remove these fallbacks APPSRE-11584
|
59
|
+
if not dt_tenant:
|
60
|
+
dt_tenant = cluster.labels.get_label_value(DTP_TENANT_LABEL)
|
61
|
+
if not token_spec_name:
|
62
|
+
token_spec_name = cluster.labels.get_label_value(DTP_SPEC_LABEL)
|
54
63
|
if not token_spec_name:
|
55
64
|
"""
|
56
65
|
We want to stay backwards compatible.
|
@@ -105,9 +105,13 @@ class FleetLabelerIntegration(QontractReconcileIntegration[NoParams]):
|
|
105
105
|
for label_default in spec.label_defaults:
|
106
106
|
match_subscription_labels = dict(label_default.match_subscription_labels)
|
107
107
|
for cluster in ocm.discover_clusters_by_labels(
|
108
|
-
labels=match_subscription_labels
|
108
|
+
labels=match_subscription_labels,
|
109
|
+
managed_prefix=spec.managed_subscription_label_prefix,
|
109
110
|
):
|
110
|
-
#
|
111
|
+
# Note, due to the nature of how our label filtering works (see ocm.py), we
|
112
|
+
# also fetch clusters that do not match the filter label.
|
113
|
+
# Here, we filter the clusters on client side.
|
114
|
+
# TODO: move this into utils.ocm module
|
111
115
|
if (
|
112
116
|
match_subscription_labels.items()
|
113
117
|
<= cluster.subscription_labels.items()
|
reconcile/fleet_labeler/ocm.py
CHANGED
@@ -71,17 +71,32 @@ class OCMClient:
|
|
71
71
|
def __init__(self, ocm_client: OCMBaseClient):
|
72
72
|
self._ocm_client = ocm_client
|
73
73
|
|
74
|
-
def discover_clusters_by_labels(
|
74
|
+
def discover_clusters_by_labels(
|
75
|
+
self, labels: Mapping[str, str], managed_prefix: str
|
76
|
+
) -> list[Cluster]:
|
75
77
|
label_filter = Filter(mode=FilterMode.AND).eq("type", "Subscription")
|
76
78
|
for key in labels:
|
77
79
|
label_filter = label_filter.eq("Key", key)
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
desired_labels_filter = (
|
81
|
+
Filter(mode=FilterMode.AND)
|
82
|
+
.eq("type", "Subscription")
|
83
|
+
.like(
|
84
|
+
"key",
|
85
|
+
f"{managed_prefix}.%",
|
86
|
+
)
|
87
|
+
)
|
88
|
+
# Note, that discover_clusters_by_labels() only fetches labels that are matching the filter!
|
89
|
+
# However, to understand current state, we also want to know the labels under managed_prefix.
|
90
|
+
# I.e., we need a fetch condition such as:
|
91
|
+
# ("{managed_prefix}.%") OR ("{key1_filter}" AND "{key2_filter}" ....)
|
92
|
+
# The above returns also clusters that do not fit the match label.
|
93
|
+
# I.e., we must filter the result on client side.
|
94
|
+
# TODO: do this in utils.ocm module
|
95
|
+
desired_filter = label_filter | desired_labels_filter
|
81
96
|
return [
|
82
97
|
Cluster.from_cluster_details(cluster)
|
83
98
|
for cluster in discover_clusters_by_labels(
|
84
|
-
ocm_api=self._ocm_client, label_filter=
|
99
|
+
ocm_api=self._ocm_client, label_filter=desired_filter
|
85
100
|
)
|
86
101
|
]
|
87
102
|
|
{qontract_reconcile-0.10.2.dev91.dist-info → qontract_reconcile-0.10.2.dev93.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|