qontract-reconcile 0.10.1rc1049__py3-none-any.whl → 0.10.1rc1051__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.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.dist-info}/RECORD +9 -9
- reconcile/cli.py +2 -14
- reconcile/dynatrace_token_provider/integration.py +30 -22
- reconcile/utils/mr/base.py +23 -0
- reconcile/utils/mr/promote_qontract.py +15 -23
- {qontract_reconcile-0.10.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.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.1rc1051
|
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.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.dist-info}/RECORD
RENAMED
@@ -10,7 +10,7 @@ reconcile/aws_iam_password_reset.py,sha256=q96mwr2KeEQ5bpNniGlgIMZTxiuLSodcYfX-t
|
|
10
10
|
reconcile/aws_support_cases_sos.py,sha256=hl_9L53yQYRQxKs3IWrd69Cc60XK067g_bJRM9B0udo,2975
|
11
11
|
reconcile/blackbox_exporter_endpoint_monitoring.py,sha256=O1wFp52EyF538c6txaWBs8eMtUIy19gyHZ6VzJ6QXS8,3512
|
12
12
|
reconcile/checkpoint.py,sha256=_JhMxrye5BgkRMxWYuf7Upli6XayPINKSsuo3ynHTRc,5010
|
13
|
-
reconcile/cli.py,sha256=
|
13
|
+
reconcile/cli.py,sha256=JCKHmEpzb1MnjtyBlyRPo27J2z03J1rrQ680Nlu7_m8,106890
|
14
14
|
reconcile/closedbox_endpoint_monitoring_base.py,sha256=rLh16BOlBOxTmJ8Si3wWyyEpmMlhh4Znx1Gc36qsmOc,4865
|
15
15
|
reconcile/cluster_deployment_mapper.py,sha256=5gumAaRCcFXsabUJ1dnuUy9WrP_FEEM5JnOnE8ch9sE,2326
|
16
16
|
reconcile/dashdotdb_base.py,sha256=l34QDu1G96_Ctnh7ZXdxXgSeCE93GQMdLAkWxmN6vDA,4775
|
@@ -181,7 +181,7 @@ 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=
|
184
|
+
reconcile/dynatrace_token_provider/integration.py,sha256=Wgjv6UkMmPa8V0baHt0zk9sv5KENVeaStdIY1j7DKqE,26049
|
185
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=66XfJact_PZoa9c8Wz0t_n8N6aSMRQpfPLgKHYtWf8s,4307
|
@@ -776,14 +776,14 @@ reconcile/utils/merge_request_manager/parser.py,sha256=5pGoz8Q6EuYXlUc1z-D0FahdR
|
|
776
776
|
reconcile/utils/mr/__init__.py,sha256=hcfHDIIIsJT4C0BnzDnyeZEfZdamrqHzMLcBzIT1ibI,2578
|
777
777
|
reconcile/utils/mr/app_interface_reporter.py,sha256=6Kpg93V9FvcOke9Jimkva359MQ-ZyBIkUpf8QIA6-to,1793
|
778
778
|
reconcile/utils/mr/aws_access.py,sha256=w-UJutB_OfBJOvr-gsPzhtBPkDfKcNZZWGGuI9cN3HI,2605
|
779
|
-
reconcile/utils/mr/base.py,sha256=
|
779
|
+
reconcile/utils/mr/base.py,sha256=UwA_jm_2vMlWg-Y3oYlGWoXLgrTLBQGKtwIasJSK9_8,8105
|
780
780
|
reconcile/utils/mr/clusters_updates.py,sha256=pcusPAwRUkvyk_-bixsRNTzSvpTLypJ1kflq5UEVgcM,2271
|
781
781
|
reconcile/utils/mr/glitchtip_access_reporter.py,sha256=i5vo9jjBifX5wIcLwEMH5_VFVg-NY-pBKe0HysSw4CQ,5031
|
782
782
|
reconcile/utils/mr/labels.py,sha256=9QRTRjZAtq45zELd9SwavaraczMjwjn5no3RK1YxFTg,825
|
783
783
|
reconcile/utils/mr/notificator.py,sha256=cp80wFzu_ZzrJPye7L1pI0H6JRGb7hOGuNxJYUq4Yr8,2967
|
784
784
|
reconcile/utils/mr/ocm_update_recommended_version.py,sha256=p_aVP0TGrlKk9WBwgQnYWqUDsED_Hg6G5Bqj0UvtRwA,1536
|
785
785
|
reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py,sha256=ojnIjw-8vRnmCCxOGBOEgPZLH4nC1hcuef74LWw2Rpk,3004
|
786
|
-
reconcile/utils/mr/promote_qontract.py,sha256=
|
786
|
+
reconcile/utils/mr/promote_qontract.py,sha256=704SOkLBioEwXITEr2mNdqpXA30J7kuUq1kQ4Q_mN8c,6693
|
787
787
|
reconcile/utils/mr/user_maintenance.py,sha256=cHPBn8zrReWLHalyk-EFdkFJe9zjVjRoZhT4t2zZfGE,3956
|
788
788
|
reconcile/utils/ocm/__init__.py,sha256=Y-bp8GomMpyCo0tFW6kJ78-ZG1UIupYRtBzbMWU0kwM,798
|
789
789
|
reconcile/utils/ocm/addons.py,sha256=_LDdJ-gapM3s5exKlIUt-MlXZTAUoHezbYBU0QmvfWQ,7335
|
@@ -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.1rc1051.dist-info/METADATA,sha256=OCC0UVReNHQheyMr9wl3_gbSoQwD8OkgyIIB5df-Y6c,2213
|
871
|
+
qontract_reconcile-0.10.1rc1051.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
872
|
+
qontract_reconcile-0.10.1rc1051.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
|
873
|
+
qontract_reconcile-0.10.1rc1051.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
874
|
+
qontract_reconcile-0.10.1rc1051.dist-info/RECORD,,
|
reconcile/cli.py
CHANGED
@@ -3107,26 +3107,14 @@ def cluster_auth_rhidp(ctx):
|
|
3107
3107
|
@integration.command(
|
3108
3108
|
short_help="Automatically provide dedicated Dynatrace tokens to management clusters"
|
3109
3109
|
)
|
3110
|
-
@click.option(
|
3111
|
-
"--ocm-org-ids",
|
3112
|
-
help="A comma seperated list of OCM organization IDs DTP should operate on. If none is specified, all organizations are considered.",
|
3113
|
-
required=False,
|
3114
|
-
envvar="DTP_OCM_ORG_IDS",
|
3115
|
-
)
|
3116
3110
|
@click.pass_context
|
3117
|
-
def dynatrace_token_provider(ctx
|
3111
|
+
def dynatrace_token_provider(ctx):
|
3118
3112
|
from reconcile.dynatrace_token_provider.integration import (
|
3119
3113
|
DynatraceTokenProviderIntegration,
|
3120
|
-
DynatraceTokenProviderIntegrationParams,
|
3121
3114
|
)
|
3122
3115
|
|
3123
|
-
parsed_ocm_org_ids = set(ocm_org_ids.split(",")) if ocm_org_ids else None
|
3124
3116
|
run_class_integration(
|
3125
|
-
integration=DynatraceTokenProviderIntegration(
|
3126
|
-
DynatraceTokenProviderIntegrationParams(
|
3127
|
-
ocm_organization_ids=parsed_ocm_org_ids,
|
3128
|
-
)
|
3129
|
-
),
|
3117
|
+
integration=DynatraceTokenProviderIntegration(),
|
3130
3118
|
ctx=ctx.obj,
|
3131
3119
|
)
|
3132
3120
|
|
@@ -38,7 +38,7 @@ from reconcile.utils.ocm.base import (
|
|
38
38
|
)
|
39
39
|
from reconcile.utils.ocm.labels import subscription_label_filter
|
40
40
|
from reconcile.utils.runtime.integration import (
|
41
|
-
|
41
|
+
NoParams,
|
42
42
|
QontractReconcileIntegration,
|
43
43
|
)
|
44
44
|
|
@@ -46,10 +46,6 @@ QONTRACT_INTEGRATION = "dynatrace-token-provider"
|
|
46
46
|
SYNCSET_AND_MANIFEST_ID = "ext-dynatrace-tokens-dtp"
|
47
47
|
|
48
48
|
|
49
|
-
class DynatraceTokenProviderIntegrationParams(PydanticRunParams):
|
50
|
-
ocm_organization_ids: set[str] | None = None
|
51
|
-
|
52
|
-
|
53
49
|
class ReconcileErrorSummary(Exception):
|
54
50
|
def __init__(self, exceptions: Iterable[str]) -> None:
|
55
51
|
self.exceptions = exceptions
|
@@ -59,11 +55,9 @@ class ReconcileErrorSummary(Exception):
|
|
59
55
|
return f"Reconcile exceptions:\n{formatted_exceptions}"
|
60
56
|
|
61
57
|
|
62
|
-
class DynatraceTokenProviderIntegration(
|
63
|
-
|
64
|
-
)
|
65
|
-
def __init__(self, params: DynatraceTokenProviderIntegrationParams) -> None:
|
66
|
-
super().__init__(params=params)
|
58
|
+
class DynatraceTokenProviderIntegration(QontractReconcileIntegration[NoParams]):
|
59
|
+
def __init__(self) -> None:
|
60
|
+
super().__init__(NoParams())
|
67
61
|
self._lock = Lock()
|
68
62
|
self._managed_tokens_cnt: dict[str, Counter[str]] = defaultdict(Counter)
|
69
63
|
|
@@ -106,6 +100,27 @@ class DynatraceTokenProviderIntegration(
|
|
106
100
|
cnt,
|
107
101
|
)
|
108
102
|
|
103
|
+
def _filter_clusters(
|
104
|
+
self,
|
105
|
+
clusters: Iterable[Cluster],
|
106
|
+
token_spec_by_name: Mapping[str, DynatraceTokenProviderTokenSpecV1],
|
107
|
+
) -> list[Cluster]:
|
108
|
+
filtered_clusters = []
|
109
|
+
for cluster in clusters:
|
110
|
+
token_spec = token_spec_by_name.get(cluster.token_spec_name)
|
111
|
+
if not token_spec:
|
112
|
+
logging.debug(
|
113
|
+
f"[{cluster.external_id=}] Skipping cluster. {cluster.token_spec_name=} does not exist."
|
114
|
+
)
|
115
|
+
continue
|
116
|
+
if cluster.organization_id in token_spec.ocm_org_ids:
|
117
|
+
filtered_clusters.append(cluster)
|
118
|
+
else:
|
119
|
+
logging.debug(
|
120
|
+
f"[{cluster.external_id=}] Skipping cluster for {token_spec.name=}. {cluster.organization_id=} is not defined in {token_spec.ocm_org_ids=}."
|
121
|
+
)
|
122
|
+
return filtered_clusters
|
123
|
+
|
109
124
|
def reconcile(self, dry_run: bool, dependencies: Dependencies) -> None:
|
110
125
|
token_specs = list(dependencies.token_spec_by_name.values())
|
111
126
|
validate_token_specs(specs=token_specs)
|
@@ -124,12 +139,10 @@ class DynatraceTokenProviderIntegration(
|
|
124
139
|
unhandled_exceptions.append(f"{ocm_env_name}: {e}")
|
125
140
|
if not clusters:
|
126
141
|
continue
|
127
|
-
|
128
|
-
clusters
|
129
|
-
|
130
|
-
|
131
|
-
if cluster.organization_id in self.params.ocm_organization_ids
|
132
|
-
]
|
142
|
+
filtered_clusters = self._filter_clusters(
|
143
|
+
clusters=clusters,
|
144
|
+
token_spec_by_name=dependencies.token_spec_by_name,
|
145
|
+
)
|
133
146
|
|
134
147
|
existing_dtp_tokens: dict[str, dict[str, str]] = {}
|
135
148
|
|
@@ -140,7 +153,7 @@ class DynatraceTokenProviderIntegration(
|
|
140
153
|
),
|
141
154
|
len(clusters),
|
142
155
|
)
|
143
|
-
for cluster in
|
156
|
+
for cluster in filtered_clusters:
|
144
157
|
try:
|
145
158
|
with DTPOrganizationErrorRate(
|
146
159
|
integration=self.name,
|
@@ -230,11 +243,6 @@ class DynatraceTokenProviderIntegration(
|
|
230
243
|
token_spec: DynatraceTokenProviderTokenSpecV1,
|
231
244
|
ocm_env_name: str,
|
232
245
|
) -> None:
|
233
|
-
if cluster.organization_id not in token_spec.ocm_org_ids:
|
234
|
-
logging.info(
|
235
|
-
f"[{token_spec.name=}] Cluster {cluster.external_id} is not part of ocm orgs defined in {token_spec.ocm_org_ids=}"
|
236
|
-
)
|
237
|
-
return
|
238
246
|
existing_data = {}
|
239
247
|
if cluster.is_hcp:
|
240
248
|
existing_data = self.get_manifest(ocm_client=ocm_client, cluster=cluster)
|
reconcile/utils/mr/base.py
CHANGED
@@ -4,12 +4,15 @@ from abc import (
|
|
4
4
|
ABC,
|
5
5
|
abstractmethod,
|
6
6
|
)
|
7
|
+
from collections.abc import Iterable
|
7
8
|
from typing import Any
|
8
9
|
from uuid import uuid4
|
9
10
|
|
10
11
|
from gitlab.exceptions import GitlabError
|
11
12
|
from jinja2 import Template
|
12
13
|
|
14
|
+
from reconcile import typed_queries
|
15
|
+
from reconcile.gql_definitions.fragments.user import User
|
13
16
|
from reconcile.utils.constants import PROJ_ROOT
|
14
17
|
from reconcile.utils.gitlab_api import GitLabApi
|
15
18
|
from reconcile.utils.mr.labels import DO_NOT_MERGE_HOLD
|
@@ -108,6 +111,26 @@ class MergeRequestBase(ABC):
|
|
108
111
|
**self.sqs_msg_data,
|
109
112
|
}
|
110
113
|
|
114
|
+
def infer_author(
|
115
|
+
self, author_email: str | None, all_users: Iterable[User] | None = None
|
116
|
+
) -> str | None:
|
117
|
+
if not author_email:
|
118
|
+
return None
|
119
|
+
if not all_users:
|
120
|
+
return None
|
121
|
+
|
122
|
+
username = author_email.split("@")[0]
|
123
|
+
users = None
|
124
|
+
if author_email.endswith(typed_queries.smtp.settings().mail_address):
|
125
|
+
users = [u for u in all_users if username == u.org_username]
|
126
|
+
elif author_email.endswith("users.noreply.github.com"):
|
127
|
+
users = [u for u in all_users if username == u.github_username]
|
128
|
+
|
129
|
+
if users:
|
130
|
+
return users[0].org_username
|
131
|
+
|
132
|
+
return None
|
133
|
+
|
111
134
|
def submit_to_sqs(self, sqs_cli: SQSGateway) -> None:
|
112
135
|
"""
|
113
136
|
Sends the MR message to SQS.
|
@@ -1,8 +1,6 @@
|
|
1
1
|
from jsonpath_ng.ext import parser
|
2
2
|
from ruamel.yaml.compat import StringIO
|
3
3
|
|
4
|
-
from reconcile import typed_queries
|
5
|
-
from reconcile.gql_definitions.fragments.user import User
|
6
4
|
from reconcile.typed_queries.users import get_users
|
7
5
|
from reconcile.utils.gitlab_api import GitLabApi
|
8
6
|
from reconcile.utils.mr.base import MergeRequestBase
|
@@ -12,9 +10,10 @@ from reconcile.utils.ruamel import create_ruamel_instance
|
|
12
10
|
class PromoteQontractSchemas(MergeRequestBase):
|
13
11
|
name = "promote_qontract_schemas"
|
14
12
|
|
15
|
-
def __init__(self, version: str):
|
13
|
+
def __init__(self, version: str, author_email: str | None = None):
|
16
14
|
self.path = ".env"
|
17
15
|
self.version = version
|
16
|
+
self.author_email = author_email
|
18
17
|
|
19
18
|
super().__init__()
|
20
19
|
|
@@ -22,7 +21,16 @@ class PromoteQontractSchemas(MergeRequestBase):
|
|
22
21
|
|
23
22
|
@property
|
24
23
|
def title(self) -> str:
|
25
|
-
|
24
|
+
author = self.infer_author(
|
25
|
+
author_email=self.author_email, all_users=get_users()
|
26
|
+
)
|
27
|
+
return f"[{self.name}] promote qontract-schemas to version {self.version}" + (
|
28
|
+
f" by @{author}"
|
29
|
+
if author
|
30
|
+
else f" by {self.author_email}"
|
31
|
+
if self.author_email
|
32
|
+
else ""
|
33
|
+
)
|
26
34
|
|
27
35
|
@property
|
28
36
|
def description(self) -> str:
|
@@ -60,27 +68,11 @@ class PromoteQontractReconcileCommercial(MergeRequestBase):
|
|
60
68
|
|
61
69
|
self.labels = []
|
62
70
|
|
63
|
-
def author(self, all_users: list[User] | None = None) -> str | None:
|
64
|
-
if not self.author_email:
|
65
|
-
return None
|
66
|
-
if not all_users:
|
67
|
-
return None
|
68
|
-
|
69
|
-
username = self.author_email.split("@")[0]
|
70
|
-
users = None
|
71
|
-
if self.author_email.endswith(typed_queries.smtp.settings().mail_address):
|
72
|
-
users = [u for u in all_users if username == u.org_username]
|
73
|
-
elif self.author_email.endswith("users.noreply.github.com"):
|
74
|
-
users = [u for u in all_users if username == u.github_username]
|
75
|
-
|
76
|
-
if users:
|
77
|
-
return users[0].org_username
|
78
|
-
|
79
|
-
return None
|
80
|
-
|
81
71
|
@property
|
82
72
|
def title(self) -> str:
|
83
|
-
author = self.
|
73
|
+
author = self.infer_author(
|
74
|
+
author_email=self.author_email, all_users=get_users()
|
75
|
+
)
|
84
76
|
return f"[{self.name}] promote qontract-reconcile to version {self.version}" + (
|
85
77
|
f" by @{author}"
|
86
78
|
if author
|
{qontract_reconcile-0.10.1rc1049.dist-info → qontract_reconcile-0.10.1rc1051.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|