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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc1049
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
@@ -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=2Qxyuwrp90j9Pox_2px5LZDn8oomwrQuFtdY85xMBOE,107389
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=Il2DIgeeOjaVtI8A7ou4SbWCo7vpiAopwDxhn5geaEo,25691
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=TP6xaxznxsF_v2KcC_D3ut1cX_4KCcx4pjIC1-4eZUY,7307
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=8cYAa2zW47ZsqqG8aQ8Akj31NQPc9ARN936_OY7t1pI,7016
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.1rc1049.dist-info/METADATA,sha256=D5PDDDmCzGGwdJ4MCHf2rBEApxpHBaSAtT97Krh_aWA,2213
871
- qontract_reconcile-0.10.1rc1049.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
872
- qontract_reconcile-0.10.1rc1049.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
873
- qontract_reconcile-0.10.1rc1049.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
874
- qontract_reconcile-0.10.1rc1049.dist-info/RECORD,,
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, ocm_org_ids):
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
- PydanticRunParams,
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
- QontractReconcileIntegration[DynatraceTokenProviderIntegrationParams]
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
- if self.params.ocm_organization_ids:
128
- clusters = [
129
- cluster
130
- for cluster in clusters
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 clusters:
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)
@@ -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
- return f"[{self.name}] promote qontract-schemas to version {self.version}"
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.author(all_users=get_users())
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