qontract-reconcile 0.10.1rc530__py3-none-any.whl → 0.10.1rc532__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.1rc530
3
+ Version: 0.10.1rc532
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
@@ -345,16 +345,15 @@ reconcile/rhidp/sso_client/base.py,sha256=EfQ2ewcOKh5idg46UKAkY6z0m_nGQfvnQKffa2
345
345
  reconcile/rhidp/sso_client/integration.py,sha256=kA8g7c38ZBSdrRtyfEqy_WgSreD1PbwY7ZIN-3tZRPc,2221
346
346
  reconcile/rhidp/sso_client/metrics.py,sha256=Tq7tSOsqL3XdcPUdozxqzSPIodUeOV87UCTqpuuqqhw,1013
347
347
  reconcile/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
348
- reconcile/saas_auto_promotions_manager/integration.py,sha256=1nm3aV5a0frEPTSww4ue1mfQ_Px6XaRZoaBRhPgJiAU,6472
348
+ reconcile/saas_auto_promotions_manager/integration.py,sha256=G_IRL85fNI8Knw31KstDPE_AXJv6VFzc5AsqMeU7CBs,5788
349
349
  reconcile/saas_auto_promotions_manager/publisher.py,sha256=4_M9Oykhj-kEZPUn05E2DY5gD6-x32Dgf7K3NPOkGEg,2029
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.py,sha256=VuSORhskZjJKgm6crgg0AfTEDbj5rtb1JHMfXA8yvxs,8133
354
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py,sha256=eEKT8lqS7Dw0oG_oykRRIYNlWmncHk-Npc1LCpcVrAw,5785
353
+ reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py,sha256=Efl4PBOt78UgB-NL_j3_FXabtpQvkJhCEXaHwyspVcE,6006
355
354
  reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py,sha256=x8Gg-YjEFWEeDPJH3Y8SrfcJbwhLuAqCz4kIhfEyaaA,7060
356
355
  reconcile/saas_auto_promotions_manager/merge_request_manager/reconciler.py,sha256=_gZ0ef-5E9hCdpkSw4b8SdTfpcaTS722KPWey4LhD5I,7644
357
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=1j9Mmq-PN_fMI45CWPKTGW9VlytcQaTyf0mQSbWPdfQ,6959
356
+ reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=sNkSKmEA1rgT2R8VNuYuHBjJWa_wpHX3M64LlOb7jB4,6959
358
357
  reconcile/saas_auto_promotions_manager/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
359
358
  reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=mihuWynroB1Cea1Lsvf6V8Nb8PGiBdcLC0uhCX_52Y0,6966
360
359
  reconcile/skupper_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -454,7 +453,7 @@ reconcile/test/test_vpc_peerings_validator.py,sha256=dFSmjc_dMN2GqMbntCFpa7PUZmy
454
453
  reconcile/test/test_wrong_region.py,sha256=7KzL7OaICQ9Z3DW27zt_ykMN7_87owAFC-2CYjvGoyA,2138
455
454
  reconcile/test/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
456
455
  reconcile/test/saas_auto_promotions_manager/conftest.py,sha256=tZNs35EuWulP53Cqt61RteOGY_uH4gfhtXfGQ8-awwM,3081
457
- reconcile/test/saas_auto_promotions_manager/test_integration_test.py,sha256=UIafVpeof9Zd3Q17mEDIUwgdBGf8oFxkf7h8tLfmwCE,2077
456
+ reconcile/test/saas_auto_promotions_manager/test_integration_test.py,sha256=fQB3V5kyTOzODbt43jQ03pfOLuAWq3nW3R9tVTWkTrQ,1729
458
457
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
459
458
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
460
459
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py,sha256=7O3lbk1EmEtUofqGncfiwMYvDPXrkQNPB59zlQ_zXkM,4588
@@ -668,8 +667,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
668
667
  tools/test/test_qontract_cli.py,sha256=d18KrdhtUGqoC7_kWZU128U0-VJEj-0rjFkLVufcI6I,2755
669
668
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
670
669
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
671
- qontract_reconcile-0.10.1rc530.dist-info/METADATA,sha256=vBKtmSp2hYuK2N6ks8hGTMvpT7L7s6ZFD3yMu1NpS8w,2349
672
- qontract_reconcile-0.10.1rc530.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
673
- qontract_reconcile-0.10.1rc530.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
674
- qontract_reconcile-0.10.1rc530.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
675
- qontract_reconcile-0.10.1rc530.dist-info/RECORD,,
670
+ qontract_reconcile-0.10.1rc532.dist-info/METADATA,sha256=3nnHvXZzInihpt9YyT72NRdKRXxmLdmKHc0cqWW86u8,2349
671
+ qontract_reconcile-0.10.1rc532.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
672
+ qontract_reconcile-0.10.1rc532.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
673
+ qontract_reconcile-0.10.1rc532.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
674
+ qontract_reconcile-0.10.1rc532.dist-info/RECORD,,
@@ -6,9 +6,6 @@ from sretoolbox.utils import threaded
6
6
  from reconcile.openshift_saas_deploy import (
7
7
  QONTRACT_INTEGRATION as OPENSHIFT_SAAS_DEPLOY,
8
8
  )
9
- from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager import (
10
- MergeRequestManager,
11
- )
12
9
  from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
13
10
  MergeRequestManagerV2,
14
11
  )
@@ -52,7 +49,6 @@ class SaasAutoPromotionsManager:
52
49
  vcs: VCS,
53
50
  saas_file_inventory: SaasFilesInventory,
54
51
  merge_request_manager_v2: MergeRequestManagerV2,
55
- merge_request_manager: MergeRequestManager,
56
52
  thread_pool_size: int,
57
53
  dry_run: bool,
58
54
  ):
@@ -60,7 +56,6 @@ class SaasAutoPromotionsManager:
60
56
  self._vcs = vcs
61
57
  self._saas_file_inventory = saas_file_inventory
62
58
  self._merge_request_manager_v2 = merge_request_manager_v2
63
- self._merge_request_manager = merge_request_manager
64
59
  self._thread_pool_size = thread_pool_size
65
60
  self._dry_run = dry_run
66
61
 
@@ -92,18 +87,12 @@ class SaasAutoPromotionsManager:
92
87
  self._fetch_publisher_real_world_states()
93
88
  self._compute_desired_subscriber_states()
94
89
  subscribers_with_diff = self._get_subscribers_with_diff()
95
- self._merge_request_manager.housekeeping()
96
- self._merge_request_manager.create_promotion_merge_requests(
97
- subscribers=subscribers_with_diff
98
- )
99
90
  self._merge_request_manager_v2.reconcile(subscribers=subscribers_with_diff)
100
91
 
101
92
 
102
93
  def init_external_dependencies(
103
94
  dry_run: bool,
104
- ) -> tuple[
105
- PromotionState, VCS, SaasFilesInventory, MergeRequestManagerV2, MergeRequestManager
106
- ]:
95
+ ) -> tuple[PromotionState, VCS, SaasFilesInventory, MergeRequestManagerV2]:
107
96
  """
108
97
  Lets initialize everything that involves calls to external dependencies:
109
98
  - VCS -> Gitlab / Github queries
@@ -137,11 +126,6 @@ def init_external_dependencies(
137
126
  mr_parser=mr_parser,
138
127
  renderer=Renderer(),
139
128
  )
140
- merge_request_manager = MergeRequestManager(
141
- mr_parser=mr_parser,
142
- renderer=Renderer(),
143
- vcs=vcs,
144
- )
145
129
  saas_files = get_saas_files()
146
130
  saas_inventory = SaasFilesInventory(saas_files=saas_files)
147
131
  deployment_state = PromotionState(
@@ -152,7 +136,6 @@ def init_external_dependencies(
152
136
  vcs,
153
137
  saas_inventory,
154
138
  merge_request_manager_v2,
155
- merge_request_manager,
156
139
  )
157
140
 
158
141
 
@@ -167,7 +150,6 @@ def run(
167
150
  vcs,
168
151
  saas_inventory,
169
152
  merge_request_manager_v2,
170
- merge_request_manager,
171
153
  ) = init_external_dependencies(dry_run=dry_run)
172
154
  if defer:
173
155
  defer(vcs.cleanup)
@@ -176,7 +158,6 @@ def run(
176
158
  deployment_state=deployment_state,
177
159
  vcs=vcs,
178
160
  saas_file_inventory=saas_inventory,
179
- merge_request_manager=merge_request_manager,
180
161
  merge_request_manager_v2=merge_request_manager_v2,
181
162
  thread_pool_size=thread_pool_size,
182
163
  dry_run=dry_run,
@@ -19,20 +19,21 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer impor
19
19
  Renderer,
20
20
  )
21
21
  from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
22
- from reconcile.utils.mr.labels import DO_NOT_MERGE_HOLD
22
+ from reconcile.utils.mr.labels import AUTO_MERGE
23
23
  from reconcile.utils.vcs import VCS
24
24
 
25
25
  BATCH_SIZE_LIMIT = 5
26
- SAPM_LABEL = "SAPMCanary"
27
- SAPM_MR_LABELS = [SAPM_LABEL, DO_NOT_MERGE_HOLD]
28
26
 
29
- MR_DESC = """
30
- :warning: **THIS IS A TEST MR - DO NOT MERGE OR CHANGE THIS!**
27
+ SAPM_LABEL = "SAPM"
28
+ SAPM_MR_LABELS = [SAPM_LABEL, AUTO_MERGE]
31
29
 
32
- If you witness any issues with this MR, please reach out to kfischer from AppSRE.
30
+ MR_DESC = """
31
+ This is an auto-promotion triggered by app-interface's [saas-auto-promotions-manager](https://github.com/app-sre/qontract-reconcile/tree/master/reconcile/saas_auto_promotions_manager) (SAPM).
32
+ This MR promotes all subscribers with auto-promotions for the channel(s) listed below.
33
33
 
34
- Please **do not remove or change any label** from this MR.
34
+ Please **do not manually modify** this MR in any way, as it might result in blocking the auto-promotion.
35
35
 
36
+ This description is used by SAPM to manage auto-promotions.
36
37
  """
37
38
 
38
39
 
@@ -120,7 +121,7 @@ class MergeRequestManagerV2:
120
121
  is_batchable=addition.batchable,
121
122
  )
122
123
  title = self._renderer.render_title(
123
- is_draft=False, canary=True, channels=description_channels
124
+ is_draft=False, canary=False, channels=description_channels
124
125
  )
125
126
  logging.info(
126
127
  "Open MR for update in channel(s) %s",
@@ -19,7 +19,7 @@ from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
19
19
  PROMOTION_DATA_SEPARATOR = (
20
20
  "**SAPM Data - DO NOT MANUALLY CHANGE ANYTHING BELOW THIS LINE**"
21
21
  )
22
- SAPM_VERSION = "2.0.0"
22
+ SAPM_VERSION = "2.1.1"
23
23
  CONTENT_HASHES = "content_hashes"
24
24
  CHANNELS_REF = "channels"
25
25
  IS_BATCHABLE = "is_batchable"
@@ -1,9 +1,6 @@
1
1
  from unittest.mock import create_autospec
2
2
 
3
3
  from reconcile.saas_auto_promotions_manager.integration import SaasAutoPromotionsManager
4
- from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager import (
5
- MergeRequestManager,
6
- )
7
4
  from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
8
5
  MergeRequestManagerV2,
9
6
  )
@@ -39,17 +36,11 @@ def test_integration_test():
39
36
  mr_parser=create_autospec(spec=MRParser),
40
37
  renderer=create_autospec(spec=Renderer),
41
38
  )
42
- merge_request_manager = MergeRequestManager(
43
- vcs=vcs,
44
- mr_parser=create_autospec(spec=MRParser),
45
- renderer=create_autospec(spec=Renderer),
46
- )
47
39
  manager = SaasAutoPromotionsManager(
48
40
  deployment_state=create_autospec(spec=PromotionState),
49
41
  saas_file_inventory=SaasFilesInventory(saas_files=[]),
50
42
  vcs=vcs,
51
43
  merge_request_manager_v2=merge_request_manager_v2,
52
- merge_request_manager=merge_request_manager,
53
44
  thread_pool_size=1,
54
45
  dry_run=False,
55
46
  )
@@ -1,190 +0,0 @@
1
- import logging
2
- import re
3
- from collections import defaultdict
4
- from collections.abc import Iterable
5
-
6
- from gitlab.exceptions import GitlabGetError
7
-
8
- from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request import (
9
- SAPMMR,
10
- )
11
- from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
12
- MRParser,
13
- OpenMergeRequest,
14
- )
15
- from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
16
- CHANNELS_REF,
17
- CONTENT_HASHES,
18
- IS_BATCHABLE,
19
- VERSION_REF,
20
- Renderer,
21
- )
22
- from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
23
- from reconcile.utils.mr.labels import AUTO_MERGE
24
- from reconcile.utils.vcs import VCS
25
-
26
- ITEM_SEPARATOR = ","
27
-
28
- SAPM_LABEL = "SAPM"
29
- SAPM_MR_LABELS = [SAPM_LABEL, AUTO_MERGE]
30
-
31
- MR_DESC = """
32
- This is an auto-promotion triggered by app-interface's [saas-auto-promotions-manager](https://github.com/app-sre/qontract-reconcile/tree/master/reconcile/saas_auto_promotions_manager) (SAPM).
33
- The channel(s) mentioned in the MR title had an event.
34
- This MR promotes all subscribers with auto-promotions for these channel(s).
35
-
36
- Please **do not remove or change any label** from this MR.
37
-
38
- Parts of this description are used by SAPM to manage auto-promotions.
39
- """
40
-
41
-
42
- class MergeRequestManager:
43
- """
44
- Manager for SAPM merge requests. This class
45
- is responsible for housekeeping (closing old/bad MRs) and
46
- opening new MRs for subscribers with a state diff.
47
-
48
- The idea is that for every channel combination there exists
49
- maximum one open MR in app-interface. I.e., all changes for
50
- a channel combination at a minumum are batched in a single MR.
51
- The MR description is used to store current state for SAPM.
52
- Channels can also be batched together into a single MR to reduce the overall
53
- amount of MRs.
54
- """
55
-
56
- def __init__(self, vcs: VCS, mr_parser: MRParser, renderer: Renderer):
57
- self._vcs = vcs
58
- self._mr_parser = mr_parser
59
- self._renderer = renderer
60
- self._version_ref_regex = re.compile(rf"{VERSION_REF}: (.*)$", re.MULTILINE)
61
- self._content_hash_regex = re.compile(rf"{CONTENT_HASHES}: (.*)$", re.MULTILINE)
62
- self._channels_regex = re.compile(rf"{CHANNELS_REF}: (.*)$", re.MULTILINE)
63
- self._is_batchable_regex = re.compile(rf"{IS_BATCHABLE}: (.*)$", re.MULTILINE)
64
- self._open_mrs: list[OpenMergeRequest] = []
65
- self._unbatchable_hashes: set[str] = set()
66
-
67
- def _unbatch_failed_mrs(self) -> None:
68
- """
69
- We optimistically batch MRs together that didnt run through MR check yet.
70
- Vast majority of auto-promotion MRs are succeeding checks, so we can stay optimistic.
71
- In the rare case of an MR failing the check, we want to unbatch it.
72
- I.e., we open a dedicated MR for each channel in the batched MR, mark the new MRs as non-batchable
73
- and close the old batched MR. By doing so, we ensure that unrelated MRs are not blocking each other.
74
- Unbatched MRs are marked and will never be batched again.
75
- """
76
- open_mrs_after_unbatching: list[OpenMergeRequest] = []
77
- for mr in self._open_mrs:
78
- if mr.is_batchable and mr.failed_mr_check:
79
- self._vcs.close_app_interface_mr(
80
- mr.raw,
81
- "Closing this MR because it failed MR check and isn't marked un-batchable yet.",
82
- )
83
- # Remember these hashes as unbatchable
84
- self._unbatchable_hashes.update(mr.content_hashes)
85
- else:
86
- open_mrs_after_unbatching.append(mr)
87
- self._open_mrs = open_mrs_after_unbatching
88
-
89
- def housekeeping(self) -> None:
90
- self._open_mrs = self._mr_parser.retrieve_open_mrs(label=SAPM_LABEL)
91
- self._unbatch_failed_mrs()
92
-
93
- def _aggregate_subscribers_per_channel_combo(
94
- self, subscribers: Iterable[Subscriber]
95
- ) -> dict[str, list[Subscriber]]:
96
- subscribers_per_channel_combo: dict[str, list[Subscriber]] = defaultdict(list)
97
- for subscriber in subscribers:
98
- channel_combo = ",".join([c.name for c in subscriber.channels])
99
- subscribers_per_channel_combo[channel_combo].append(subscriber)
100
- return subscribers_per_channel_combo
101
-
102
- def _merge_request_already_exists(self, channels: str, content_hash: str) -> bool:
103
- return any(
104
- True
105
- for mr in self._open_mrs
106
- if content_hash in mr.content_hashes and channels in mr.channels
107
- )
108
-
109
- def create_promotion_merge_requests(
110
- self, subscribers: Iterable[Subscriber]
111
- ) -> None:
112
- """
113
- Open new MR for channel combinations with new content.
114
- If there is new content, close any existing MR for that
115
- channel combination.
116
- """
117
- subscribers_per_channel_combo = self._aggregate_subscribers_per_channel_combo(
118
- subscribers=subscribers
119
- )
120
- for channel_combo, subs in subscribers_per_channel_combo.items():
121
- combined_content_hash = Subscriber.combined_content_hash(subscribers=subs)
122
- if self._merge_request_already_exists(
123
- content_hash=combined_content_hash, channels=channel_combo
124
- ):
125
- logging.info(
126
- "There is already an open merge request for channel(s) %s - skipping",
127
- channel_combo,
128
- )
129
- continue
130
- for mr in self._open_mrs:
131
- if channel_combo not in mr.channels:
132
- continue
133
- if combined_content_hash not in mr.content_hashes:
134
- logging.info(
135
- "Closing MR %s because it has out-dated content",
136
- mr.raw.attributes.get("web_url", "NO_WEBURL"),
137
- )
138
- self._vcs.close_app_interface_mr(
139
- mr=mr.raw,
140
- comment="Closing this MR because it has out-dated content.",
141
- )
142
- content_by_path: dict[str, str] = {}
143
- has_error = False
144
- for sub in subs:
145
- if sub.target_file_path not in content_by_path:
146
- try:
147
- content_by_path[sub.target_file_path] = (
148
- self._vcs.get_file_content_from_app_interface_master(
149
- file_path=sub.target_file_path
150
- )
151
- )
152
- except GitlabGetError as e:
153
- if e.response_code == 404:
154
- logging.error(
155
- "The saas file %s does not exist anylonger. Most likely qontract-server data not in synch. This should resolve soon on its own.",
156
- sub.target_file_path,
157
- )
158
- has_error = True
159
- break
160
- raise e
161
- content_by_path[sub.target_file_path] = (
162
- self._renderer.render_merge_request_content(
163
- subscriber=sub,
164
- current_content=content_by_path[sub.target_file_path],
165
- )
166
- )
167
- if has_error:
168
- continue
169
-
170
- description = self._renderer.render_description(
171
- message=MR_DESC,
172
- content_hashes=combined_content_hash,
173
- channels=channel_combo,
174
- is_batchable=combined_content_hash not in self._unbatchable_hashes,
175
- )
176
- title = self._renderer.render_title(
177
- is_draft=False, canary=False, channels=channel_combo
178
- )
179
- logging.info(
180
- "Open MR for update in channel(s) %s",
181
- channel_combo,
182
- )
183
- self._vcs.open_app_interface_merge_request(
184
- mr=SAPMMR(
185
- labels=SAPM_MR_LABELS,
186
- content_by_path=content_by_path,
187
- title=title,
188
- description=description,
189
- )
190
- )