qontract-reconcile 0.10.1rc535__py3-none-any.whl → 0.10.1rc537__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.1rc535
3
+ Version: 0.10.1rc537
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
@@ -1,5 +1,5 @@
1
1
  reconcile/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- reconcile/acs_policies.py,sha256=Mop44Z5T0DxXghme13ZVvy1hr5KphZKzc_ZevxAJBQ0,8784
2
+ reconcile/acs_policies.py,sha256=e_kVyP4rGm3fJzq10Anr8scZoPenlmTcoS5REK0d2T0,9144
3
3
  reconcile/acs_rbac.py,sha256=YoKu5wTRTtb3EGT0PV3r279LDgvw2ECb-0_0j4suScg,23032
4
4
  reconcile/aws_ami_share.py,sha256=eeu0TI3M5yyUaozyAq_aW3tir-9be4YFguOXvIvKHSo,3757
5
5
  reconcile/aws_ecr_image_pull_secrets.py,sha256=TGEc_0nv8oxV2HqA8VdcM4HHP-B1YqmNOOU6FPwVFTY,2328
@@ -350,9 +350,10 @@ reconcile/saas_auto_promotions_manager/publisher.py,sha256=4_M9Oykhj-kEZPUn05E2D
350
350
  reconcile/saas_auto_promotions_manager/subscriber.py,sha256=cLhPlkT71J2LIice3SLmH1WpsqzV46gd0peMxrnqyRw,7452
351
351
  reconcile/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
352
352
  reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request.py,sha256=BeAJWLow7b4HQyZ9zz398sQkPeIz8chpMkCts2NU27c,1282
353
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py,sha256=Efl4PBOt78UgB-NL_j3_FXabtpQvkJhCEXaHwyspVcE,6006
353
+ reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py,sha256=mU6csC1-2WjEHhYNCeEDDmN63QQIprp0zkqQ5UH5xNM,6817
354
+ reconcile/saas_auto_promotions_manager/merge_request_manager/metrics.py,sha256=mI9yYwCiNePmtox16yKH1mU5ijsMeQYjQBgRiZq101A,878
354
355
  reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py,sha256=x8Gg-YjEFWEeDPJH3Y8SrfcJbwhLuAqCz4kIhfEyaaA,7060
355
- reconcile/saas_auto_promotions_manager/merge_request_manager/reconciler.py,sha256=lxQUJgpwfnzvGZTNpmLOeTSiXzzJta1aSezMF9HRTwg,7734
356
+ reconcile/saas_auto_promotions_manager/merge_request_manager/reconciler.py,sha256=nst5ZynEQs9Hy9Z2DAjN8_ALIS_5XnrbJh7KG4YVRrE,7789
356
357
  reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=huslpgeXNf_VmEVmWHIYYSwEcT67zsbuubYMk2P9ezc,6959
357
358
  reconcile/saas_auto_promotions_manager/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
358
359
  reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=mihuWynroB1Cea1Lsvf6V8Nb8PGiBdcLC0uhCX_52Y0,6966
@@ -374,7 +375,7 @@ reconcile/templates/jira-checkpoint-missinginfo.j2,sha256=c_Vvg-lEENsB3tgxm9B6Y9
374
375
  reconcile/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
375
376
  reconcile/test/conftest.py,sha256=rQousYrxUz-EwAIbsYO6bIwR1B4CrOz9y_zaUVo2lfI,4466
376
377
  reconcile/test/fixtures.py,sha256=9SDWAUlSd1rCx7z3GhULHcpr-I6FyCsXxaFAZIqYQsQ,591
377
- reconcile/test/test_acs_policies.py,sha256=2hioxQ1AlbtW-jerw9YiQ8aIb0YjFpzDFs1j6pvn-Nc,15133
378
+ reconcile/test/test_acs_policies.py,sha256=hMnCX9KdLRKb53gYXK4JUR5yJwhczJRyyUPywDeLeLg,15716
378
379
  reconcile/test/test_acs_rbac.py,sha256=lvNd8GY0-GHzcOdOn13QWdrqbBXXKzNT7EEDHNH7cjM,28272
379
380
  reconcile/test/test_aggregated_list.py,sha256=iiWitQuNYC58aimWaiBoE4NROHjr1NCgQ91MnHEG_Ro,6412
380
381
  reconcile/test/test_amtool.py,sha256=vxRhGieeydMBOb9UI2ziMHjJa8puMeGNsUhGhy-yMnk,1032
@@ -458,9 +459,9 @@ reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py,sh
458
459
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
459
460
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py,sha256=7O3lbk1EmEtUofqGncfiwMYvDPXrkQNPB59zlQ_zXkM,4588
460
461
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py,sha256=Z1IV51OUuzhd-3S8W-k7ixC-fkaglCokn0eakK0Z73s,606
461
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py,sha256=ryROiiQNtZvuG820CB-RQ9FMmLAGshezyMDNDiJNA_E,2369
462
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py,sha256=h8lnorFPZIxTtbaaXGLoiEsBbB4Qj-Mg9BKV62ZqEBQ,2389
462
463
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py,sha256=dcGHzxuafKSxmswSO1qF2WlKaqsmEvtERC6Lb8kDAN0,10019
463
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py,sha256=to7lRzKTqN1cwEcnzDUKPWbIAzffI9jD870en0-zif8,17868
464
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py,sha256=_bzfJzjFJgubu--7wyXIiusUrdbmLtFbHmkbat4SX_M,17828
464
465
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
465
466
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py,sha256=2rCSstewp4LPoEJHm5N7dGJexEtY8ndLHvoGZYjmpsc,1678
466
467
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/data_keys.py,sha256=beHYQ9kgDLeBZgC2FvxQA3tHx1PO-RAMN8_kVcSdikI,90
@@ -589,7 +590,7 @@ reconcile/utils/vaultsecretref.py,sha256=3Ed2uBy36TzSvL0B-l4FoWQqB2SbBKDKEuUPIO6
589
590
  reconcile/utils/vcs.py,sha256=o1r0n_IrU2El75CED_6sjR2GZGM-exuWsj5F7jONaMU,6779
590
591
  reconcile/utils/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
591
592
  reconcile/utils/acs/base.py,sha256=Qih-xZ3RBJZEE291iHHlv7lUY6ShcAvSj1PA3_aTTnM,2276
592
- reconcile/utils/acs/policies.py,sha256=utDmFKb6pbBN3W6JFxRrlr9yFwL3aQurGDywaFGM6w0,5196
593
+ reconcile/utils/acs/policies.py,sha256=_jAz6cv8KRYtDsXjGoJgNbD8_9PUa5LSwwVlpK4A_cQ,5505
593
594
  reconcile/utils/acs/rbac.py,sha256=ugsLM9Pb7FbUbdq85E3VzXGMaB9ZovXob7tdWCxwqZ8,8808
594
595
  reconcile/utils/cloud_resource_best_practice/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
595
596
  reconcile/utils/cloud_resource_best_practice/aws_rds.py,sha256=EvE6XKLsrZ531MJptKqPht2lOETrOjySTHXk6CzMgo0,2279
@@ -667,8 +668,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
667
668
  tools/test/test_qontract_cli.py,sha256=d18KrdhtUGqoC7_kWZU128U0-VJEj-0rjFkLVufcI6I,2755
668
669
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
669
670
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
670
- qontract_reconcile-0.10.1rc535.dist-info/METADATA,sha256=mnMNUfrE1xFYJmiIcrSIdaiF0EYFAOaEH494u33aBcw,2349
671
- qontract_reconcile-0.10.1rc535.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
672
- qontract_reconcile-0.10.1rc535.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
673
- qontract_reconcile-0.10.1rc535.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
674
- qontract_reconcile-0.10.1rc535.dist-info/RECORD,,
671
+ qontract_reconcile-0.10.1rc537.dist-info/METADATA,sha256=dGXxQQQzpUMW_Kyo_ktrTXrUVvKSJ9GMS7SG5jKdMoo,2349
672
+ qontract_reconcile-0.10.1rc537.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
673
+ qontract_reconcile-0.10.1rc537.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
674
+ qontract_reconcile-0.10.1rc537.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
675
+ qontract_reconcile-0.10.1rc537.dist-info/RECORD,,
reconcile/acs_policies.py CHANGED
@@ -58,7 +58,10 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
58
58
  return self.qontract_integration.replace("_", "-")
59
59
 
60
60
  def _build_policy(
61
- self, gql_policy: AcsPolicyV1, notifier_name_to_id: dict[str, str]
61
+ self,
62
+ gql_policy: AcsPolicyV1,
63
+ notifier_name_to_id: dict[str, str],
64
+ cluster_name_to_id: dict[str, str],
62
65
  ) -> Policy:
63
66
  conditions = [
64
67
  pc for c in gql_policy.conditions if (pc := self._build_policy_condition(c))
@@ -72,7 +75,7 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
72
75
  severity=f"{gql_policy.severity.upper()}_SEVERITY", # align with acs api severity value format
73
76
  scope=sorted(
74
77
  [
75
- Scope(cluster=cs.name, namespace="")
78
+ Scope(cluster=cluster_name_to_id[cs.name], namespace="")
76
79
  for cs in cast(
77
80
  gql_acs_policies.AcsPolicyScopeClusterV1,
78
81
  gql_policy.scope,
@@ -83,7 +86,9 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
83
86
  if gql_policy.scope.level == "cluster"
84
87
  else sorted(
85
88
  [
86
- Scope(cluster=ns.cluster.name, namespace=ns.name)
89
+ Scope(
90
+ cluster=cluster_name_to_id[ns.cluster.name], namespace=ns.name
91
+ )
87
92
  for ns in cast(
88
93
  gql_acs_policies.AcsPolicyScopeNamespaceV1,
89
94
  gql_policy.scope,
@@ -158,7 +163,10 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
158
163
  return None
159
164
 
160
165
  def get_desired_state(
161
- self, query_func: Callable, notifiers: list[AcsPolicyApi.NotifierIdentifiers]
166
+ self,
167
+ query_func: Callable,
168
+ notifiers: list[AcsPolicyApi.NotifierIdentifiers],
169
+ clusters: list[AcsPolicyApi.ClusterIdentifiers],
162
170
  ) -> list[Policy]:
163
171
  """
164
172
  Get desired ACS security policies and convert to acs api policy object format
@@ -167,8 +175,9 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
167
175
  :return: list of utils.acs.policies.Policy derived from acs-policy-1 definitions
168
176
  """
169
177
  notifier_name_to_id = {n.name: n.id for n in notifiers}
178
+ cluster_name_to_id = {c.name: c.id for c in clusters}
170
179
  return [
171
- self._build_policy(gql_policy, notifier_name_to_id)
180
+ self._build_policy(gql_policy, notifier_name_to_id, cluster_name_to_id)
172
181
  for gql_policy in gql_acs_policies.query(query_func=query_func).acs_policies
173
182
  or []
174
183
  ]
@@ -225,7 +234,8 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
225
234
  instance={"url": instance.url, "token": token[instance.credentials.field]}
226
235
  ) as acs_api:
227
236
  notifiers = acs_api.list_notifiers()
228
- desired = self.get_desired_state(gqlapi.query, notifiers)
237
+ clusters = acs_api.list_clusters()
238
+ desired = self.get_desired_state(gqlapi.query, notifiers, clusters)
229
239
  current = acs_api.get_custom_policies()
230
240
  self.reconcile(
231
241
  desired=desired, current=current, acs=acs_api, dry_run=dry_run
@@ -7,6 +7,15 @@ from gitlab.exceptions import GitlabGetError
7
7
  from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request import (
8
8
  SAPMMR,
9
9
  )
10
+ from reconcile.saas_auto_promotions_manager.merge_request_manager.metrics import (
11
+ SAPMClosedMRsCounter as MRClosedCounter,
12
+ )
13
+ from reconcile.saas_auto_promotions_manager.merge_request_manager.metrics import (
14
+ SAPMOpenedMRsCounter as MROpenedCounter,
15
+ )
16
+ from reconcile.saas_auto_promotions_manager.merge_request_manager.metrics import (
17
+ SAPMParallelOpenMRsGauge as ParallelOpenMRGauge,
18
+ )
10
19
  from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
11
20
  MRParser,
12
21
  )
@@ -19,6 +28,7 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer impor
19
28
  Renderer,
20
29
  )
21
30
  from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
31
+ from reconcile.utils import metrics
22
32
  from reconcile.utils.mr.labels import AUTO_MERGE
23
33
  from reconcile.utils.vcs import VCS
24
34
 
@@ -138,19 +148,32 @@ class MergeRequestManagerV2:
138
148
 
139
149
  def reconcile(self, subscribers: Iterable[Subscriber]) -> None:
140
150
  current_state = self._mr_parser.retrieve_open_mrs(label=SAPM_LABEL)
151
+ metrics.set_gauge(ParallelOpenMRGauge(), len(current_state))
152
+
141
153
  desired_state = self._aggregate_desired_state(subscribers=subscribers)
154
+
142
155
  diff = self._reconciler.reconcile(
143
156
  batch_limit=BATCH_SIZE_LIMIT,
144
157
  desired_promotions=desired_state,
145
158
  open_mrs=current_state,
146
159
  )
147
160
  for deletion in diff.deletions:
161
+ metrics.inc_counter(
162
+ MRClosedCounter(
163
+ reason=deletion.reason.name,
164
+ ),
165
+ )
148
166
  self._vcs.close_app_interface_mr(
149
167
  mr=deletion.mr.raw,
150
- comment=deletion.reason,
168
+ comment=deletion.reason.value,
151
169
  )
152
170
 
153
171
  for addition in diff.additions:
172
+ metrics.inc_counter(
173
+ MROpenedCounter(
174
+ is_batchable=addition.batchable,
175
+ ),
176
+ )
154
177
  self._render_mr(addition=addition)
155
178
 
156
179
  for rendered_mr in self._sapm_mrs:
@@ -0,0 +1,40 @@
1
+ from pydantic import BaseModel
2
+
3
+ from reconcile.utils.metrics import (
4
+ CounterMetric,
5
+ GaugeMetric,
6
+ )
7
+
8
+
9
+ class SAPMBaseMetric(BaseModel):
10
+ "Base class for SAPM MR metrics"
11
+
12
+ integration: str = "saas_auto_promotions_manager"
13
+
14
+
15
+ class SAPMOpenedMRsCounter(SAPMBaseMetric, CounterMetric):
16
+ "Counter for the number of opened auto-promotion MRs"
17
+
18
+ is_batchable: bool
19
+
20
+ @classmethod
21
+ def name(cls) -> str:
22
+ return "sapm_opened_mrs"
23
+
24
+
25
+ class SAPMClosedMRsCounter(SAPMBaseMetric, CounterMetric):
26
+ "Counter for the number of closed auto-promotion MRs"
27
+
28
+ reason: str
29
+
30
+ @classmethod
31
+ def name(cls) -> str:
32
+ return "sapm_closed_mrs"
33
+
34
+
35
+ class SAPMParallelOpenMRsGauge(SAPMBaseMetric, GaugeMetric):
36
+ "Gauge for the number of parallel open auto-promotion MRs"
37
+
38
+ @classmethod
39
+ def name(cls) -> str:
40
+ return "sapm_parallel_open_mrs"
@@ -1,14 +1,17 @@
1
1
  from collections.abc import Iterable
2
2
  from dataclasses import dataclass
3
+ from enum import Enum
3
4
  from typing import Optional
4
5
 
5
6
  from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
6
7
  OpenMergeRequest,
7
8
  )
8
9
 
9
- MSG_MISSING_UNBATCHING = "Closing this MR because it failed MR check and isn't marked as un-batchable yet. cc @kfischer"
10
- MSG_OUTDATED_CONTENT = "Closing this MR because it has out-dated content."
11
- MSG_NEW_BATCH = "Closing this MR in favor of a new batch MR."
10
+
11
+ class Reason(Enum):
12
+ MISSING_UNBATCHING = "Closing this MR because it failed MR check and isn't marked as un-batchable yet. cc @kfischer"
13
+ OUTDATED_CONTENT = "Closing this MR because it has out-dated content."
14
+ NEW_BATCH = "Closing this MR in favor of a new batch MR."
12
15
 
13
16
 
14
17
  @dataclass
@@ -20,7 +23,7 @@ class Promotion:
20
23
  @dataclass
21
24
  class Deletion:
22
25
  mr: OpenMergeRequest
23
- reason: str
26
+ reason: Reason
24
27
 
25
28
 
26
29
  @dataclass
@@ -70,7 +73,7 @@ class Reconciler:
70
73
  diff.deletions.append(
71
74
  Deletion(
72
75
  mr=mr,
73
- reason=MSG_MISSING_UNBATCHING,
76
+ reason=Reason.MISSING_UNBATCHING,
74
77
  )
75
78
  )
76
79
  else:
@@ -112,7 +115,7 @@ class Reconciler:
112
115
  diff.deletions.append(
113
116
  Deletion(
114
117
  mr=mr,
115
- reason=MSG_OUTDATED_CONTENT,
118
+ reason=Reason.OUTDATED_CONTENT,
116
119
  )
117
120
  )
118
121
  self._open_mrs = open_mrs_after_deletion
@@ -163,7 +166,7 @@ class Reconciler:
163
166
  diff.deletions.append(
164
167
  Deletion(
165
168
  mr=batch_with_capacity,
166
- reason=MSG_NEW_BATCH,
169
+ reason=Reason.NEW_BATCH,
167
170
  )
168
171
  )
169
172
 
@@ -14,6 +14,7 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler imp
14
14
  Addition,
15
15
  Deletion,
16
16
  Diff,
17
+ Reason,
17
18
  Reconciler,
18
19
  )
19
20
  from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
@@ -48,7 +49,7 @@ def test_reconcile(
48
49
  failed_mr_check=False,
49
50
  is_batchable=True,
50
51
  ),
51
- reason="some reason.",
52
+ reason=Reason.NEW_BATCH,
52
53
  )
53
54
 
54
55
  additions = [
@@ -76,7 +77,7 @@ def test_reconcile(
76
77
 
77
78
  assert len(manager._sapm_mrs) == len(additions)
78
79
  vcs.close_app_interface_mr.assert_has_calls([
79
- call(deletion.mr.raw, deletion.reason),
80
+ call(deletion.mr.raw, deletion.reason.value),
80
81
  ])
81
82
  vcs.open_app_interface_merge_request.assert_has_calls([
82
83
  call(mr) for mr in manager._sapm_mrs
@@ -8,13 +8,11 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser impo
8
8
  OpenMergeRequest,
9
9
  )
10
10
  from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
11
- MSG_MISSING_UNBATCHING,
12
- MSG_NEW_BATCH,
13
- MSG_OUTDATED_CONTENT,
14
11
  Addition,
15
12
  Deletion,
16
13
  Diff,
17
14
  Promotion,
15
+ Reason,
18
16
  Reconciler,
19
17
  )
20
18
 
@@ -110,7 +108,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
110
108
  failed_mr_check=True,
111
109
  is_batchable=True,
112
110
  ),
113
- reason=MSG_MISSING_UNBATCHING,
111
+ reason=Reason.MISSING_UNBATCHING,
114
112
  ),
115
113
  Deletion(
116
114
  mr=OpenMergeRequest(
@@ -120,7 +118,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
120
118
  failed_mr_check=False,
121
119
  is_batchable=True,
122
120
  ),
123
- reason=MSG_OUTDATED_CONTENT,
121
+ reason=Reason.OUTDATED_CONTENT,
124
122
  ),
125
123
  Deletion(
126
124
  mr=OpenMergeRequest(
@@ -130,7 +128,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
130
128
  failed_mr_check=False,
131
129
  is_batchable=False,
132
130
  ),
133
- reason=MSG_OUTDATED_CONTENT,
131
+ reason=Reason.OUTDATED_CONTENT,
134
132
  ),
135
133
  Deletion(
136
134
  mr=OpenMergeRequest(
@@ -140,7 +138,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
140
138
  failed_mr_check=True,
141
139
  is_batchable=False,
142
140
  ),
143
- reason=MSG_OUTDATED_CONTENT,
141
+ reason=Reason.OUTDATED_CONTENT,
144
142
  ),
145
143
  ],
146
144
  additions=[],
@@ -181,7 +179,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
181
179
  failed_mr_check=True,
182
180
  is_batchable=True,
183
181
  ),
184
- reason=MSG_MISSING_UNBATCHING,
182
+ reason=Reason.MISSING_UNBATCHING,
185
183
  )
186
184
  ],
187
185
  additions=[
@@ -263,7 +261,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
263
261
  failed_mr_check=False,
264
262
  is_batchable=True,
265
263
  ),
266
- reason=MSG_NEW_BATCH,
264
+ reason=Reason.NEW_BATCH,
267
265
  )
268
266
  ],
269
267
  additions=[
@@ -321,7 +319,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
321
319
  failed_mr_check=False,
322
320
  is_batchable=True,
323
321
  ),
324
- reason=MSG_NEW_BATCH,
322
+ reason=Reason.NEW_BATCH,
325
323
  )
326
324
  ],
327
325
  additions=[
@@ -20,6 +20,10 @@ from reconcile.gql_definitions.acs.acs_policies import (
20
20
  )
21
21
  from reconcile.utils.acs.policies import AcsPolicyApi, Policy, PolicyCondition, Scope
22
22
 
23
+ CLUSTER_NAME_ONE = "app-sre-stage"
24
+ CLUSTER_ID_ONE = "5211d395-5cf7-4185-a1fb-d88f41bc7542"
25
+ CLUSTER_NAME_TWO = "app-sre-prod"
26
+ CLUSTER_ID_TWO = "a217cca7-d85a-4be1-9703-f58866fdbe2d"
23
27
  CUSTOM_POLICY_ONE_NAME = "app-sre-clusters-fixable-cve-7-fixable"
24
28
  CUSTOM_POLICY_ONE_ID = "365d4e71-3241-4448-9f3d-eb0eed1c1820"
25
29
  CUSTOM_POLICY_TWO_NAME = "app-sre-namespaces-severity-critical"
@@ -41,8 +45,8 @@ def query_data_desired_state() -> AcsPolicyQueryData:
41
45
  scope=AcsPolicyScopeClusterV1(
42
46
  level="cluster",
43
47
  clusters=[
44
- ClusterV1(name="app-sre-stage"),
45
- ClusterV1(name="app-sre-prod"),
48
+ ClusterV1(name=CLUSTER_NAME_ONE),
49
+ ClusterV1(name=CLUSTER_NAME_TWO),
46
50
  ],
47
51
  ),
48
52
  conditions=[
@@ -91,8 +95,8 @@ def modeled_acs_policies() -> list[Policy]:
91
95
  notifiers=[JIRA_NOTIFIER_ID],
92
96
  categories=["Vulnerability Management"],
93
97
  scope=[
94
- Scope(cluster="app-sre-prod", namespace=""),
95
- Scope(cluster="app-sre-stage", namespace=""),
98
+ Scope(cluster=CLUSTER_ID_ONE, namespace=""),
99
+ Scope(cluster=CLUSTER_ID_TWO, namespace=""),
96
100
  ],
97
101
  conditions=[
98
102
  PolicyCondition(field_name="CVSS", values=[">=7"], negate=False),
@@ -106,8 +110,8 @@ def modeled_acs_policies() -> list[Policy]:
106
110
  notifiers=[],
107
111
  categories=["DevOps Best Practices", "Vulnerability Management"],
108
112
  scope=[
109
- Scope(cluster="app-sre-prod", namespace="app-interface-production"),
110
- Scope(cluster="app-sre-stage", namespace="app-interface-stage"),
113
+ Scope(cluster=CLUSTER_ID_ONE, namespace="app-interface-stage"),
114
+ Scope(cluster=CLUSTER_ID_TWO, namespace="app-interface-production"),
111
115
  ],
112
116
  conditions=[
113
117
  PolicyCondition(
@@ -175,8 +179,8 @@ def api_response_policies_specific() -> list[Any]:
175
179
  "eventSource": "NOT_APPLICABLE",
176
180
  "exclusions": [],
177
181
  "scope": [
178
- {"cluster": "app-sre-stage", "namespace": "", "label": None},
179
- {"cluster": "app-sre-prod", "namespace": "", "label": None},
182
+ {"cluster": CLUSTER_ID_ONE, "namespace": "", "label": None},
183
+ {"cluster": CLUSTER_ID_TWO, "namespace": "", "label": None},
180
184
  ],
181
185
  "severity": "HIGH_SEVERITY",
182
186
  "enforcementActions": [],
@@ -216,12 +220,12 @@ def api_response_policies_specific() -> list[Any]:
216
220
  "exclusions": [],
217
221
  "scope": [
218
222
  {
219
- "cluster": "app-sre-stage",
223
+ "cluster": CLUSTER_ID_ONE,
220
224
  "namespace": "app-interface-stage",
221
225
  "label": None,
222
226
  },
223
227
  {
224
- "cluster": "app-sre-prod",
228
+ "cluster": CLUSTER_ID_TWO,
225
229
  "namespace": "app-interface-production",
226
230
  "label": None,
227
231
  },
@@ -257,11 +261,20 @@ def api_response_list_notifiers() -> list[AcsPolicyApi.NotifierIdentifiers]:
257
261
  ]
258
262
 
259
263
 
264
+ @pytest.fixture
265
+ def api_response_list_clusters() -> list[AcsPolicyApi.ClusterIdentifiers]:
266
+ return [
267
+ AcsPolicyApi.ClusterIdentifiers(id=CLUSTER_ID_ONE, name=CLUSTER_NAME_ONE),
268
+ AcsPolicyApi.ClusterIdentifiers(id=CLUSTER_ID_TWO, name=CLUSTER_NAME_TWO),
269
+ ]
270
+
271
+
260
272
  def test_get_desired_state(
261
273
  mocker: MockerFixture,
262
274
  query_data_desired_state: AcsPolicyQueryData,
263
275
  modeled_acs_policies: list[Policy],
264
276
  api_response_list_notifiers: list[AcsPolicyApi.NotifierIdentifiers],
277
+ api_response_list_clusters: list[AcsPolicyApi.ClusterIdentifiers],
265
278
  ) -> None:
266
279
  query_func = mocker.patch(
267
280
  "reconcile.gql_definitions.acs.acs_policies.query", autospec=True
@@ -270,7 +283,9 @@ def test_get_desired_state(
270
283
 
271
284
  integration = AcsPoliciesIntegration()
272
285
  result = integration.get_desired_state(
273
- query_func=query_func, notifiers=api_response_list_notifiers
286
+ query_func=query_func,
287
+ notifiers=api_response_list_notifiers,
288
+ clusters=api_response_list_clusters,
274
289
  )
275
290
  assert result == modeled_acs_policies
276
291
 
@@ -151,3 +151,13 @@ class AcsPolicyApi(AcsBaseApi):
151
151
  self.NotifierIdentifiers(id=c["id"], name=c["name"])
152
152
  for c in self.generic_request("/v1/notifiers", "GET").json()["notifiers"]
153
153
  ]
154
+
155
+ class ClusterIdentifiers(BaseModel):
156
+ id: str
157
+ name: str
158
+
159
+ def list_clusters(self) -> list[ClusterIdentifiers]:
160
+ return [
161
+ self.ClusterIdentifiers(id=c["id"], name=c["name"])
162
+ for c in self.generic_request("/v1/clusters", "GET").json()["clusters"]
163
+ ]