qontract-reconcile 0.10.1rc889__py3-none-any.whl → 0.10.1rc891__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.1rc889
3
+ Version: 0.10.1rc891
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
@@ -812,7 +812,7 @@ tools/app_interface_metrics_exporter.py,sha256=zkwkxdAUAxjdc-pzx2_oJXG25fo0Fnyd5
812
812
  tools/app_interface_reporter.py,sha256=uy9eRHf6EdvD8ZY2WYdroGXm18DOdnqVZyxaWN3Bm_0,17724
813
813
  tools/glitchtip_access_reporter.py,sha256=oPBnk_YoDuljU3v0FaChzOwwnk4vap1xEE67QEjzdqs,2948
814
814
  tools/glitchtip_access_revalidation.py,sha256=8kbBJk04mkq28kWoRDDkfCGIF3GRg3pJrFAh1sW0dbk,2821
815
- tools/qontract_cli.py,sha256=rm3Hr02hJT4mqBJIw3qfi2G2TQ0a0xO0CGWYPZMncCQ,122947
815
+ tools/qontract_cli.py,sha256=lEK5alQqOXQryqdpWwrZPmWUWx3YYL60armyCu4Dguc,123885
816
816
  tools/sd_app_sre_alert_report.py,sha256=e9vAdyenUz2f5c8-z-5WY0wv-SJ9aePKDH2r4IwB6pc,5063
817
817
  tools/template_validation.py,sha256=qpKYaTgk0GOPGa2Ct5_5sKdwIHtCAKIBGzsMPuJU5fw,3371
818
818
  tools/cli_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -833,18 +833,18 @@ tools/saas_metrics_exporter/commit_distance/channel.py,sha256=XEAh3eL8TmgMe7V2Bs
833
833
  tools/saas_metrics_exporter/commit_distance/commit_distance.py,sha256=pUWaZfZf0TYOwAW0gDdU8cYgTR586J_8S_DWxqHMWNA,3116
834
834
  tools/saas_metrics_exporter/commit_distance/metrics.py,sha256=5-y6n-sGACAS3eJ5ndY-2BFxcd0fxLfhvZmmBHu4JuA,426
835
835
  tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
836
- tools/saas_promotion_state/saas_promotion_state.py,sha256=_jP9E8-VcWho6FIOGdcjNN6uvMVhpdXOMHw59qNnEmE,2855
836
+ tools/saas_promotion_state/saas_promotion_state.py,sha256=5LJ9rygZ304vxfsIuRfuxueoYRb72EZNKKITEcJ4Mtk,3908
837
837
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
838
838
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
839
839
  tools/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
840
840
  tools/test/conftest.py,sha256=YLtiauk_StNFE-lirLnfG_BpJmlB2NGMZISE9A4zwvk,2421
841
841
  tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvftCWEEf-g1mfXOtgCog-g,1271
842
842
  tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jrss,4941
843
- tools/test/test_saas_promotion_state.py,sha256=48Qe5UA5WTI5NVgL7Nz0TSS77osetcijfHNCNdsHfSI,2726
843
+ tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
844
844
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
845
845
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
846
- qontract_reconcile-0.10.1rc889.dist-info/METADATA,sha256=6mFOXr_MkHFuKSqB3aKVOJP0Qi8ju9uRTqZGxCw0pZk,2273
847
- qontract_reconcile-0.10.1rc889.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
848
- qontract_reconcile-0.10.1rc889.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
849
- qontract_reconcile-0.10.1rc889.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
850
- qontract_reconcile-0.10.1rc889.dist-info/RECORD,,
846
+ qontract_reconcile-0.10.1rc891.dist-info/METADATA,sha256=VHFngce2-Z5G085gT1WzeoGZ2wj8M4njctG48i9QHHw,2273
847
+ qontract_reconcile-0.10.1rc891.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
848
+ qontract_reconcile-0.10.1rc891.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
849
+ qontract_reconcile-0.10.1rc891.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
850
+ qontract_reconcile-0.10.1rc891.dist-info/RECORD,,
tools/qontract_cli.py CHANGED
@@ -3690,6 +3690,27 @@ def get_promotion_state(channel: str, sha: str):
3690
3690
  print(state)
3691
3691
 
3692
3692
 
3693
+ @root.command()
3694
+ @click.option("--channel", help="the channel that state is part of")
3695
+ @click.option("--sha", help="the commit sha we want state for")
3696
+ @click.option("--publisher-id", help="the publisher id we want state for")
3697
+ @environ(["APP_INTERFACE_STATE_BUCKET"])
3698
+ def mark_promotion_state_successful(channel: str, sha: str, publisher_id: str):
3699
+ from tools.saas_promotion_state.saas_promotion_state import (
3700
+ SaasPromotionState,
3701
+ )
3702
+
3703
+ promotion_state = SaasPromotionState.create(promotion_state=None, saas_files=None)
3704
+ print(f"Current states for {publisher_id=}")
3705
+ print(promotion_state.get(channel=channel, sha=sha).get(publisher_id, None))
3706
+ print()
3707
+ print("Pushing new state ...")
3708
+ promotion_state.set_successful(channel=channel, sha=sha, publisher_uid=publisher_id)
3709
+ print()
3710
+ print(f"New state for {publisher_id=}")
3711
+ print(promotion_state.get(channel=channel, sha=sha).get(publisher_id, None))
3712
+
3713
+
3693
3714
  @root.command()
3694
3715
  @click.option("--change-type-name")
3695
3716
  @click.option("--role-name")
@@ -14,6 +14,14 @@ from reconcile.utils.secret_reader import create_secret_reader
14
14
  from reconcile.utils.state import init_state
15
15
 
16
16
 
17
+ class SaasPromotionStateException(Exception):
18
+ pass
19
+
20
+
21
+ class SaasPromotionStateMissingException(Exception):
22
+ pass
23
+
24
+
17
25
  class SaasPromotionState:
18
26
  def __init__(
19
27
  self, promotion_state: PromotionState, saas_files: Iterable[SaasFile]
@@ -54,6 +62,31 @@ class SaasPromotionState:
54
62
  )
55
63
  }
56
64
 
65
+ def set_successful(self, channel: str, sha: str, publisher_uid: str) -> None:
66
+ current_data = self._promotion_state.get_promotion_data(
67
+ sha=sha,
68
+ channel=channel,
69
+ target_uid=publisher_uid,
70
+ use_cache=False,
71
+ pre_check_sha_exists=False,
72
+ )
73
+
74
+ if not current_data:
75
+ raise SaasPromotionStateMissingException(
76
+ f"No promotion state in S3 for given {publisher_uid=} {sha=} {channel=}"
77
+ )
78
+
79
+ if current_data.success:
80
+ raise SaasPromotionStateException(
81
+ f"The current promotion state is already marked successful for given {publisher_uid=} {sha=} {channel=}",
82
+ current_data,
83
+ )
84
+
85
+ current_data.success = True
86
+ self._promotion_state.publish_promotion_data(
87
+ data=current_data, sha=sha, channel=channel, target_uid=publisher_uid
88
+ )
89
+
57
90
  @staticmethod
58
91
  def create(
59
92
  promotion_state: PromotionState | None, saas_files: Iterable[SaasFile] | None
@@ -7,14 +7,18 @@ from unittest.mock import (
7
7
  create_autospec,
8
8
  )
9
9
 
10
+ from pytest import raises
11
+
10
12
  from reconcile.typed_queries.saas_files import SaasFile
11
13
  from reconcile.utils.promotion_state import PromotionData, PromotionState
12
14
  from tools.saas_promotion_state.saas_promotion_state import (
13
15
  SaasPromotionState,
16
+ SaasPromotionStateException,
17
+ SaasPromotionStateMissingException,
14
18
  )
15
19
 
16
20
 
17
- def test_saas_promotion_state(
21
+ def test_get_saas_promotion_state(
18
22
  saas_files_builder: Callable[[Iterable[Mapping]], list[SaasFile]],
19
23
  ) -> None:
20
24
  saas_files = saas_files_builder([
@@ -84,3 +88,100 @@ def test_saas_promotion_state(
84
88
  target_uid="616af45d7fad7f4eea8d52b8b5e8a058cef82ab0",
85
89
  pre_check_sha_exists=False,
86
90
  )
91
+
92
+
93
+ def test_set_saas_promotion_state_success(
94
+ saas_files_builder: Callable[[Iterable[Mapping]], list[SaasFile]],
95
+ ) -> None:
96
+ saas_files = saas_files_builder([{"resourceTemplates": []}])
97
+
98
+ current_data = PromotionData(
99
+ check_in="test1",
100
+ saas_file="test2",
101
+ success=False,
102
+ target_config_hash="test3",
103
+ )
104
+ promotion_state = create_autospec(spec=PromotionState)
105
+ promotion_state.get_promotion_data.return_value = current_data
106
+ saas_promotion_state = SaasPromotionState.create(
107
+ promotion_state=promotion_state, saas_files=saas_files
108
+ )
109
+ saas_promotion_state.set_successful(
110
+ channel="test-channel", sha="test-sha", publisher_uid="test-uid"
111
+ )
112
+
113
+ promotion_state.get_promotion_data.assert_called_once_with(
114
+ sha="test-sha",
115
+ channel="test-channel",
116
+ use_cache=False,
117
+ target_uid="test-uid",
118
+ pre_check_sha_exists=False,
119
+ )
120
+ promotion_state.publish_promotion_data.assert_called_once_with(
121
+ data=PromotionData(
122
+ check_in="test1",
123
+ saas_file="test2",
124
+ success=True,
125
+ target_config_hash="test3",
126
+ ),
127
+ channel="test-channel",
128
+ sha="test-sha",
129
+ target_uid="test-uid",
130
+ )
131
+
132
+
133
+ def test_set_saas_promotion_state_missing(
134
+ saas_files_builder: Callable[[Iterable[Mapping]], list[SaasFile]],
135
+ ) -> None:
136
+ saas_files = saas_files_builder([{"resourceTemplates": []}])
137
+ promotion_state = create_autospec(spec=PromotionState)
138
+ promotion_state.get_promotion_data.return_value = None
139
+ saas_promotion_state = SaasPromotionState.create(
140
+ promotion_state=promotion_state, saas_files=saas_files
141
+ )
142
+
143
+ with raises(SaasPromotionStateMissingException):
144
+ saas_promotion_state.set_successful(
145
+ channel="test-channel", sha="test-sha", publisher_uid="test-uid"
146
+ )
147
+
148
+ promotion_state.get_promotion_data.assert_called_once_with(
149
+ sha="test-sha",
150
+ channel="test-channel",
151
+ use_cache=False,
152
+ target_uid="test-uid",
153
+ pre_check_sha_exists=False,
154
+ )
155
+ promotion_state.publish_promotion_data.assert_not_called()
156
+
157
+
158
+ def test_set_saas_promotion_state_already_successful(
159
+ saas_files_builder: Callable[[Iterable[Mapping]], list[SaasFile]],
160
+ ) -> None:
161
+ saas_files = saas_files_builder([{"resourceTemplates": []}])
162
+
163
+ current_data = PromotionData(
164
+ check_in="test1",
165
+ saas_file="test2",
166
+ success=True,
167
+ target_config_hash="test3",
168
+ )
169
+ promotion_state = create_autospec(spec=PromotionState)
170
+ promotion_state.get_promotion_data.return_value = current_data
171
+ saas_promotion_state = SaasPromotionState.create(
172
+ promotion_state=promotion_state, saas_files=saas_files
173
+ )
174
+
175
+ with raises(SaasPromotionStateException):
176
+ saas_promotion_state.set_successful(
177
+ channel="test-channel", sha="test-sha", publisher_uid="test-uid"
178
+ )
179
+
180
+ promotion_state.get_promotion_data.assert_called_once_with(
181
+ sha="test-sha",
182
+ channel="test-channel",
183
+ use_cache=False,
184
+ target_uid="test-uid",
185
+ pre_check_sha_exists=False,
186
+ )
187
+ promotion_state.publish_promotion_data.assert_not_called()