qontract-reconcile 0.10.1rc923__py3-none-any.whl → 0.10.1rc924__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.1rc923
3
+ Version: 0.10.1rc924
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
@@ -537,7 +537,7 @@ reconcile/test/test_quay_repos.py,sha256=TdkcRF_a8PLp01Kti9eZZN-vGup2yPBT4Iba3k0
537
537
  reconcile/test/test_queries.py,sha256=SpH3RmNpBjEr_ne3VjAMCgKK8RE1z1zo7bypkT5uoO4,1946
538
538
  reconcile/test/test_repo_owners.py,sha256=uRYMLbMmh-9usF0TerabZTZV-Z1CS4I6ybT-LQqCLe8,1423
539
539
  reconcile/test/test_requests_sender.py,sha256=7fd9C2kEFS0-CYtlsif66N1kO9c44pzuBPAJKR9igqU,5385
540
- reconcile/test/test_saasherder.py,sha256=f_8W8RC5di6IgiqtFaeRi6E9RJ43MGU2zFsLR_p30FQ,54524
540
+ reconcile/test/test_saasherder.py,sha256=jUn8d1DtdXq1pfDrThqIwx37Lgxa7mou3aZ-m3UrWdc,57129
541
541
  reconcile/test/test_saasherder_allowed_secret_paths.py,sha256=5NHQwNJO66at6HiyMZ5sVRTQDwxdvlOQo0KmkBWCw5Q,4853
542
542
  reconcile/test/test_secret_reader.py,sha256=kz7nzcPjvA08cytnvcA_PMA98AEyqJWsESkYeRn5xCk,4994
543
543
  reconcile/test/test_slack_base.py,sha256=pTUGvJ2S2wF3PhJyGWmiNXG52QtXKy2cbu-G8Ymrv6I,5019
@@ -689,7 +689,7 @@ reconcile/utils/pagerduty_api.py,sha256=_24i9S_4X7nlvHb-7clXRE0p1BG4ODjOzKxWO-F9
689
689
  reconcile/utils/parse_dhms_duration.py,sha256=TONpLnec5gHeF7k815YNJpQyDjXhkxZIcv9s8ffbTSY,1840
690
690
  reconcile/utils/password_validator.py,sha256=XwuWg-8CPlcuG7dl_oQ1G1h2gSVSnfMym_VkuprpWVg,2183
691
691
  reconcile/utils/prometheus.py,sha256=Ad0rwLbxRuuYjHwkwJloHEdK0bvy42h-p-HIT1DhDhs,3832
692
- reconcile/utils/promotion_state.py,sha256=Sd3otIb54vgpEe0JhFG1tkXhPS51LItmkI19pZJhDbE,3607
692
+ reconcile/utils/promotion_state.py,sha256=drkR0PSzfsUVPB0pisARzvUfHgk8KPbeK4FUZdP099Y,3894
693
693
  reconcile/utils/promtool.py,sha256=UmBfTHgW9Ys7fZ9BfhIVJEFGLkbge9y1AgL5PNHp7iA,2831
694
694
  reconcile/utils/quay_api.py,sha256=zbwi3YjL7dTDYHGWcrZ0mbxyZQuEB8v3sV_Km2O-mIs,7906
695
695
  reconcile/utils/raw_github_api.py,sha256=O6Q4vq7bi5ZWcfquPutc9rJ4Ef8_sFqd_RLgzpIoj0w,2920
@@ -793,7 +793,7 @@ reconcile/utils/runtime/sharding.py,sha256=r0ieUtNed7NvknSw6qQrCkKpVXE1shuHGnfFc
793
793
  reconcile/utils/saasherder/__init__.py,sha256=J3MBZBFa5YmhqYm08QsjBXz8mFcVOCiOCkyIcw41t7E,343
794
794
  reconcile/utils/saasherder/interfaces.py,sha256=C2wrw34OXypshVocAsPrVZsSHptgw4g9u7Haa2wulZQ,9087
795
795
  reconcile/utils/saasherder/models.py,sha256=6MGie9SqsyP5ySjmk5bO5vPJ0-x53a0uzABxQO-WsB0,9746
796
- reconcile/utils/saasherder/saasherder.py,sha256=H3pLQAD6EkjwrFpfQN73LKPg8mYRilssIcZ9M3duizU,84555
796
+ reconcile/utils/saasherder/saasherder.py,sha256=ZTDf6uIpke6y9jKZgESjdY8hDI6Jf2J2UGZp6LJXBWY,85249
797
797
  reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
798
798
  reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
799
799
  reconcile/utils/terraform/config_client.py,sha256=3gUIIIEv52Vx7-VgQ2FZYfCCrfqUv_5gw_TQ3mbLcTs,4666
@@ -844,8 +844,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
844
844
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
845
845
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
846
846
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
847
- qontract_reconcile-0.10.1rc923.dist-info/METADATA,sha256=OjR8Y-8f7JvaPxAt_N-8baMq5aI7LwcbOL2Cirs809I,2273
848
- qontract_reconcile-0.10.1rc923.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
849
- qontract_reconcile-0.10.1rc923.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
850
- qontract_reconcile-0.10.1rc923.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
851
- qontract_reconcile-0.10.1rc923.dist-info/RECORD,,
847
+ qontract_reconcile-0.10.1rc924.dist-info/METADATA,sha256=lDNUw1z1rLZBkUJGhvbJutmyOh-8hG0mfjXu2C88-Ck,2273
848
+ qontract_reconcile-0.10.1rc924.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
849
+ qontract_reconcile-0.10.1rc924.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
850
+ qontract_reconcile-0.10.1rc924.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
851
+ qontract_reconcile-0.10.1rc924.dist-info/RECORD,,
@@ -1085,6 +1085,7 @@ class TestConfigHashPromotionsValidation(TestCase):
1085
1085
  "success": True,
1086
1086
  "saas_file": self.saas_file.name,
1087
1087
  "target_config_hash": "ed2af38cf21f268c",
1088
+ "has_succeeded_once": True,
1088
1089
  }
1089
1090
  self.state_mock.get.return_value = publisher_state
1090
1091
  result = self.saasherder.validate_promotions()
@@ -1101,16 +1102,19 @@ class TestConfigHashPromotionsValidation(TestCase):
1101
1102
  "success": True,
1102
1103
  "saas_file": self.saas_file.name,
1103
1104
  "target_config_hash": "ed2af38cf21f268c",
1105
+ "has_succeeded_once": True,
1104
1106
  },
1105
1107
  {
1106
1108
  "success": True,
1107
1109
  "saas_file": self.saas_file.name,
1108
1110
  "target_config_hash": "ed2af38cf21f268c",
1111
+ "has_succeeded_once": True,
1109
1112
  },
1110
1113
  {
1111
1114
  "success": True,
1112
1115
  "saas_file": self.saas_file.name,
1113
1116
  "target_config_hash": "will_not_match",
1117
+ "has_succeeded_once": True,
1114
1118
  },
1115
1119
  ]
1116
1120
  self.state_mock.get.side_effect = publisher_states
@@ -1137,6 +1141,7 @@ class TestConfigHashPromotionsValidation(TestCase):
1137
1141
  "success": True,
1138
1142
  "saas_file": self.saas_file.name,
1139
1143
  "target_config_hash": "whatever",
1144
+ "has_succeeded_once": True,
1140
1145
  }
1141
1146
 
1142
1147
  self.assertEqual(len(self.saasherder.promotions), 4)
@@ -1148,6 +1153,62 @@ class TestConfigHashPromotionsValidation(TestCase):
1148
1153
  result = self.saasherder.validate_promotions()
1149
1154
  self.assertTrue(result)
1150
1155
 
1156
+ def test_promotion_state_re_deployment_failed(self) -> None:
1157
+ """A promotion is valid if it has ever succeeded for that ref.
1158
+ Re-deployment results should be neglected for validation.
1159
+ """
1160
+ publisher_state = {
1161
+ # Latest state is failed ...
1162
+ "success": False,
1163
+ "saas_file": self.saas_file.name,
1164
+ "target_config_hash": "ed2af38cf21f268c",
1165
+ # ... however, the deployment succeeded sometime before once.
1166
+ "has_succeeded_once": True,
1167
+ }
1168
+ self.state_mock.get.return_value = publisher_state
1169
+ result = self.saasherder.validate_promotions()
1170
+ self.assertTrue(result)
1171
+
1172
+ def test_promotion_state_never_successfully_deployed(self) -> None:
1173
+ """A promotion is invalid, if it never succeeded before."""
1174
+ publisher_state = {
1175
+ # Latest state is failed ...
1176
+ "success": False,
1177
+ "saas_file": self.saas_file.name,
1178
+ "target_config_hash": "ed2af38cf21f268c",
1179
+ # ... and it never succeeded once before.
1180
+ "has_succeeded_once": False,
1181
+ }
1182
+ self.state_mock.get.return_value = publisher_state
1183
+ result = self.saasherder.validate_promotions()
1184
+ self.assertFalse(result)
1185
+
1186
+ def test_promotion_state_success_backwards_compatibility_success(self) -> None:
1187
+ """Not all states have the has_succeeded_once attribute yet.
1188
+ If it doesnt exist, we should always fall back to latest success state.
1189
+ """
1190
+ publisher_state = {
1191
+ "success": True,
1192
+ "saas_file": self.saas_file.name,
1193
+ "target_config_hash": "ed2af38cf21f268c",
1194
+ }
1195
+ self.state_mock.get.return_value = publisher_state
1196
+ result = self.saasherder.validate_promotions()
1197
+ self.assertTrue(result)
1198
+
1199
+ def test_promotion_state_success_backwards_compatibility_fail(self) -> None:
1200
+ """Not all states have the has_succeeded_once attribute yet.
1201
+ If it doesnt exist, we should always fall back to latest success state.
1202
+ """
1203
+ publisher_state = {
1204
+ "success": False,
1205
+ "saas_file": self.saas_file.name,
1206
+ "target_config_hash": "ed2af38cf21f268c",
1207
+ }
1208
+ self.state_mock.get.return_value = publisher_state
1209
+ result = self.saasherder.validate_promotions()
1210
+ self.assertFalse(result)
1211
+
1151
1212
 
1152
1213
  @pytest.mark.usefixtures("inject_gql_class_factory")
1153
1214
  class TestSoakDays(TestCase):
@@ -18,10 +18,15 @@ class PromotionData(BaseModel):
18
18
  requirements.
19
19
  """
20
20
 
21
+ # The success is primarily used for SAPM auto-promotions
21
22
  success: bool
22
23
  target_config_hash: str | None
23
24
  saas_file: str | None
24
25
  check_in: str | None
26
+ # Whether this promotion has ever succeeded
27
+ # Note, this shouldnt be overridden on subsequent promotions of same ref
28
+ # This attribute is primarily used by saasherder validations
29
+ has_succeeded_once: bool | None
25
30
 
26
31
  class Config:
27
32
  smart_union = True
@@ -1846,7 +1846,9 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1846
1846
  target_uid=target_uid,
1847
1847
  pre_check_sha_exists=False,
1848
1848
  )
1849
- if not (deployment and deployment.success):
1849
+ if not (
1850
+ deployment and (deployment.success or deployment.has_succeeded_once)
1851
+ ):
1850
1852
  logging.error(
1851
1853
  f"Commit {promotion.commit_sha} was not "
1852
1854
  + f"published with success to channel {channel.name}"
@@ -1943,6 +1945,17 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1943
1945
  all_subscribed_saas_file_paths = set()
1944
1946
  all_subscribed_target_paths = set()
1945
1947
  for channel in promotion.publish:
1948
+ # make sure we keep some attributes on re-deployments of same ref
1949
+ has_succeeded_once = success
1950
+ current_state = self._promotion_state.get_promotion_data(
1951
+ sha=promotion.commit_sha,
1952
+ channel=channel,
1953
+ target_uid=promotion.saas_target_uid,
1954
+ use_cache=True,
1955
+ )
1956
+ if current_state and current_state.has_succeeded_once:
1957
+ has_succeeded_once = True
1958
+
1946
1959
  # publish to state to pass promotion gate
1947
1960
  self._promotion_state.publish_promotion_data(
1948
1961
  sha=promotion.commit_sha,
@@ -1952,6 +1965,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1952
1965
  saas_file=promotion.saas_file,
1953
1966
  success=success,
1954
1967
  target_config_hash=promotion.target_config_hash,
1968
+ has_succeeded_once=has_succeeded_once,
1955
1969
  # TODO: do not override - check if timestamp already exists
1956
1970
  check_in=str(now),
1957
1971
  ),