qontract-reconcile 0.10.1rc877__py3-none-any.whl → 0.10.1rc878__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.
- {qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/RECORD +12 -12
- reconcile/gql_definitions/common/saas_files.py +14 -0
- reconcile/gql_definitions/common/saas_target_namespaces.py +4 -0
- reconcile/gql_definitions/fragments/saas_target_namespace.py +6 -0
- reconcile/test/test_saasherder.py +59 -0
- reconcile/utils/saasherder/interfaces.py +8 -0
- reconcile/utils/saasherder/models.py +1 -0
- reconcile/utils/saasherder/saasherder.py +14 -0
- {qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc878
|
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
|
{qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/RECORD
RENAMED
@@ -258,8 +258,8 @@ reconcile/gql_definitions/common/pgp_reencryption_settings.py,sha256=NPLmO6J-zSu
|
|
258
258
|
reconcile/gql_definitions/common/pipeline_providers.py,sha256=JJgmmghqLIwjKOdcWYHPnf4PDgAq4GF7046i0ozrqgI,9127
|
259
259
|
reconcile/gql_definitions/common/quay_instances.py,sha256=toBkdYYVTmEafezAHZKgaW-mQ29xEW6jeronzsAlNyI,1786
|
260
260
|
reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
|
261
|
-
reconcile/gql_definitions/common/saas_files.py,sha256=
|
262
|
-
reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=
|
261
|
+
reconcile/gql_definitions/common/saas_files.py,sha256=rt-ugGWWO148cE_8-cbRkNPJ4peYDQoAnSZ3c5qT_dk,16390
|
262
|
+
reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=ZmX9SYoLQnjTc9zU6ehFNUs_GgOedim3v73A-83Gnsc,2813
|
263
263
|
reconcile/gql_definitions/common/saasherder_settings.py,sha256=nqQLcMwYxLseqq0BEcVvmrpIj2eQq0h8XDSpLN6GGCw,1793
|
264
264
|
reconcile/gql_definitions/common/slack_workspaces.py,sha256=2o0kgi4QiaRuNmZJnc_By4F6NsKIdRaXkrufRQw7Nok,1753
|
265
265
|
reconcile/gql_definitions/common/smtp_client_settings.py,sha256=JU6t6D-Qj-z1gLlgUiHKe0W7AxWQdty9jlv-ig_43tM,2248
|
@@ -299,7 +299,7 @@ reconcile/gql_definitions/fragments/prometheus_instance.py,sha256=12ltnV9kdEw6Ln
|
|
299
299
|
reconcile/gql_definitions/fragments/resource_limits_requirements.py,sha256=ucskQ_a8RxvFl5-IWxz5kk3g4-5Pvh_W4N3nLmuKxi0,744
|
300
300
|
reconcile/gql_definitions/fragments/resource_requests_requirements.py,sha256=TFKO4YALFPanSvZvIJFz0dCioBU7i73Q6hkDtGMvs9I,736
|
301
301
|
reconcile/gql_definitions/fragments/resource_values.py,sha256=-N2lNRhWp8PgocmIeX3U9f3l90Q97N2lXoq1pXdb_LE,742
|
302
|
-
reconcile/gql_definitions/fragments/saas_target_namespace.py,sha256=
|
302
|
+
reconcile/gql_definitions/fragments/saas_target_namespace.py,sha256=Ei39iL5J5TzeYtoBqbUF6zog3ctXTK-ZQyvbIVcUI20,3921
|
303
303
|
reconcile/gql_definitions/fragments/terraform_state.py,sha256=S5QuTR9YlvUObiU7hevS9ybxZEssWoRGqCR9YtGwePs,1024
|
304
304
|
reconcile/gql_definitions/fragments/upgrade_policy.py,sha256=cVza8zfra1E3yBsHiS-hKbys17fvv572GFnKshJjluE,1246
|
305
305
|
reconcile/gql_definitions/fragments/user.py,sha256=84RGYYSYnZmyrwHlCX89-EgAu7UaLFOTMQXobmHCfz8,939
|
@@ -535,7 +535,7 @@ reconcile/test/test_quay_repos.py,sha256=TdkcRF_a8PLp01Kti9eZZN-vGup2yPBT4Iba3k0
|
|
535
535
|
reconcile/test/test_queries.py,sha256=SpH3RmNpBjEr_ne3VjAMCgKK8RE1z1zo7bypkT5uoO4,1946
|
536
536
|
reconcile/test/test_repo_owners.py,sha256=uRYMLbMmh-9usF0TerabZTZV-Z1CS4I6ybT-LQqCLe8,1423
|
537
537
|
reconcile/test/test_requests_sender.py,sha256=7fd9C2kEFS0-CYtlsif66N1kO9c44pzuBPAJKR9igqU,5385
|
538
|
-
reconcile/test/test_saasherder.py,sha256=
|
538
|
+
reconcile/test/test_saasherder.py,sha256=fdjcygNFPz1YyU2uB-8IU3yQZr6MlD8np2_fYUsL2b8,54440
|
539
539
|
reconcile/test/test_saasherder_allowed_secret_paths.py,sha256=5NHQwNJO66at6HiyMZ5sVRTQDwxdvlOQo0KmkBWCw5Q,4853
|
540
540
|
reconcile/test/test_secret_reader.py,sha256=kz7nzcPjvA08cytnvcA_PMA98AEyqJWsESkYeRn5xCk,4994
|
541
541
|
reconcile/test/test_slack_base.py,sha256=gpbWOLNxMMX6fyAbs1JakhLTnwfedb3f7WpUae4tQZE,5060
|
@@ -787,9 +787,9 @@ reconcile/utils/runtime/meta.py,sha256=X44HzyXIBprf3zcsGr2XLCgoeFkz6r3U2nlFXM1H7
|
|
787
787
|
reconcile/utils/runtime/runner.py,sha256=72cc-I6yXyPov8UCLHpyERRy1eiMLpGite2roO0yUlo,7979
|
788
788
|
reconcile/utils/runtime/sharding.py,sha256=roCdbnBklhTK_g34zbgQYqzpKPaNQ8J6Xd9XLO9-t6Q,16258
|
789
789
|
reconcile/utils/saasherder/__init__.py,sha256=J3MBZBFa5YmhqYm08QsjBXz8mFcVOCiOCkyIcw41t7E,343
|
790
|
-
reconcile/utils/saasherder/interfaces.py,sha256=
|
791
|
-
reconcile/utils/saasherder/models.py,sha256=
|
792
|
-
reconcile/utils/saasherder/saasherder.py,sha256=
|
790
|
+
reconcile/utils/saasherder/interfaces.py,sha256=q7Xhs95RMwOCCqlfjelqWJOiUqhPYkpL20XaOMRxEZs,9321
|
791
|
+
reconcile/utils/saasherder/models.py,sha256=iLQZGXMx4FYnK62MJKkVp1T32BpsZ88NOcU7RW0WyAk,5579
|
792
|
+
reconcile/utils/saasherder/saasherder.py,sha256=cQhyuBGUbtFL8_1lMDRwnrSaYC88C_ApgcaBruZ7BZ4,87523
|
793
793
|
reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
|
794
794
|
reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
|
795
795
|
reconcile/utils/terraform/config_client.py,sha256=py-Ree-QUYD6Hvng6bM40VgSuttteehIKNgwOSoJO1o,4706
|
@@ -837,8 +837,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
837
837
|
tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jrss,4941
|
838
838
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
839
839
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
840
|
-
qontract_reconcile-0.10.
|
841
|
-
qontract_reconcile-0.10.
|
842
|
-
qontract_reconcile-0.10.
|
843
|
-
qontract_reconcile-0.10.
|
844
|
-
qontract_reconcile-0.10.
|
840
|
+
qontract_reconcile-0.10.1rc878.dist-info/METADATA,sha256=yc6zH-3Cqe1m2HcHSAx5gtwBQGqkbkGv3wpeOBz8b2M,2273
|
841
|
+
qontract_reconcile-0.10.1rc878.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
842
|
+
qontract_reconcile-0.10.1rc878.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
|
843
|
+
qontract_reconcile-0.10.1rc878.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
844
|
+
qontract_reconcile-0.10.1rc878.dist-info/RECORD,,
|
@@ -82,6 +82,10 @@ fragment SaasTargetNamespace on Namespace_v1 {
|
|
82
82
|
name
|
83
83
|
email
|
84
84
|
}
|
85
|
+
codeComponents {
|
86
|
+
url
|
87
|
+
hotfixVersions
|
88
|
+
}
|
85
89
|
}
|
86
90
|
cluster {
|
87
91
|
name
|
@@ -137,6 +141,10 @@ query SaasFiles {
|
|
137
141
|
name
|
138
142
|
email
|
139
143
|
}
|
144
|
+
codeComponents {
|
145
|
+
url
|
146
|
+
hotfixVersions
|
147
|
+
}
|
140
148
|
}
|
141
149
|
pipelinesProvider {
|
142
150
|
name
|
@@ -320,11 +328,17 @@ class OwnerV1(ConfiguredBaseModel):
|
|
320
328
|
email: str = Field(..., alias="email")
|
321
329
|
|
322
330
|
|
331
|
+
class AppCodeComponentsV1(ConfiguredBaseModel):
|
332
|
+
url: str = Field(..., alias="url")
|
333
|
+
hotfix_versions: Optional[list[str]] = Field(..., alias="hotfixVersions")
|
334
|
+
|
335
|
+
|
323
336
|
class AppV1(ConfiguredBaseModel):
|
324
337
|
name: str = Field(..., alias="name")
|
325
338
|
parent_app: Optional[AppV1_AppV1] = Field(..., alias="parentApp")
|
326
339
|
self_service_roles: Optional[list[RoleV1]] = Field(..., alias="selfServiceRoles")
|
327
340
|
service_owners: Optional[list[OwnerV1]] = Field(..., alias="serviceOwners")
|
341
|
+
code_components: Optional[list[AppCodeComponentsV1]] = Field(..., alias="codeComponents")
|
328
342
|
|
329
343
|
|
330
344
|
class PipelinesProviderV1(ConfiguredBaseModel):
|
@@ -52,12 +52,18 @@ class OwnerV1(ConfiguredBaseModel):
|
|
52
52
|
email: str = Field(..., alias="email")
|
53
53
|
|
54
54
|
|
55
|
+
class AppCodeComponentsV1(ConfiguredBaseModel):
|
56
|
+
url: str = Field(..., alias="url")
|
57
|
+
hotfix_versions: Optional[list[str]] = Field(..., alias="hotfixVersions")
|
58
|
+
|
59
|
+
|
55
60
|
class AppV1(ConfiguredBaseModel):
|
56
61
|
name: str = Field(..., alias="name")
|
57
62
|
parent_app: Optional[AppV1_AppV1] = Field(..., alias="parentApp")
|
58
63
|
labels: Optional[Json] = Field(..., alias="labels")
|
59
64
|
self_service_roles: Optional[list[RoleV1]] = Field(..., alias="selfServiceRoles")
|
60
65
|
service_owners: Optional[list[OwnerV1]] = Field(..., alias="serviceOwners")
|
66
|
+
code_components: Optional[list[AppCodeComponentsV1]] = Field(..., alias="codeComponents")
|
61
67
|
|
62
68
|
|
63
69
|
class DisableClusterAutomationsV1(ConfiguredBaseModel):
|
@@ -33,9 +33,12 @@ from reconcile.typed_queries.saas_files import (
|
|
33
33
|
)
|
34
34
|
from reconcile.utils.jjb_client import JJB
|
35
35
|
from reconcile.utils.openshift_resource import ResourceInventory
|
36
|
+
from reconcile.utils.promotion_state import PromotionData
|
36
37
|
from reconcile.utils.saasherder import SaasHerder
|
37
38
|
from reconcile.utils.saasherder.interfaces import SaasFile as SaasFileInterface
|
38
39
|
from reconcile.utils.saasherder.models import (
|
40
|
+
Channel,
|
41
|
+
Promotion,
|
39
42
|
TriggerSpecContainerImage,
|
40
43
|
TriggerSpecMovingCommit,
|
41
44
|
TriggerSpecUpstreamJob,
|
@@ -1350,6 +1353,62 @@ class TestRemoveNoneAttributes(TestCase):
|
|
1350
1353
|
self.assertEqual(res, expected)
|
1351
1354
|
|
1352
1355
|
|
1356
|
+
@pytest.mark.usefixtures("inject_gql_class_factory")
|
1357
|
+
class TestPromotionHoxfixVersions(TestCase):
|
1358
|
+
def setUp(self) -> None:
|
1359
|
+
self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
|
1360
|
+
SaasFile,
|
1361
|
+
Fixtures("saasherder").get_anymarkup("saas.gql.yml"),
|
1362
|
+
)
|
1363
|
+
self.state_patcher = patch("reconcile.utils.state.State", autospec=True)
|
1364
|
+
self.state_mock = self.state_patcher.start().return_value
|
1365
|
+
self.saasherder = SaasHerder(
|
1366
|
+
[self.saas_file],
|
1367
|
+
secret_reader=MockSecretReader(),
|
1368
|
+
thread_pool_size=1,
|
1369
|
+
state=self.state_mock,
|
1370
|
+
integration="",
|
1371
|
+
integration_version="",
|
1372
|
+
hash_length=7,
|
1373
|
+
repo_url="https://repo-url.com",
|
1374
|
+
)
|
1375
|
+
self.promotion_state_patcher = patch(
|
1376
|
+
"reconcile.utils.promotion_state.PromotionState", autospec=True
|
1377
|
+
)
|
1378
|
+
self.promotion_state_mock = self.promotion_state_patcher.start().return_value
|
1379
|
+
self.saasherder._promotion_state = self.promotion_state_mock
|
1380
|
+
|
1381
|
+
def tearDown(self) -> None:
|
1382
|
+
self.state_patcher.stop()
|
1383
|
+
self.promotion_state_patcher.stop()
|
1384
|
+
|
1385
|
+
def test_hotfix_version_valid_promotion(self) -> None:
|
1386
|
+
code_component_url = "https://github.com/app-sre/test-saas-deployments"
|
1387
|
+
hotfix_version = "1234567890123456789012345678901234567890"
|
1388
|
+
# code_component = self.saas_file.app.code_components[0]
|
1389
|
+
channel = Channel(
|
1390
|
+
name="",
|
1391
|
+
publisher_uids=[""],
|
1392
|
+
)
|
1393
|
+
promotion = Promotion(
|
1394
|
+
url=code_component_url,
|
1395
|
+
commit_sha=hotfix_version,
|
1396
|
+
saas_file=self.saas_file.name,
|
1397
|
+
target_config_hash="",
|
1398
|
+
saas_target_uid="",
|
1399
|
+
soak_days=0,
|
1400
|
+
subscribe=[channel],
|
1401
|
+
)
|
1402
|
+
self.saasherder.promotions = [promotion]
|
1403
|
+
self.promotion_state_mock.get_promotion_data.return_value = PromotionData(
|
1404
|
+
success=False
|
1405
|
+
)
|
1406
|
+
self.assertFalse(self.saasherder.validate_promotions())
|
1407
|
+
|
1408
|
+
self.saasherder.hotfix_versions[code_component_url] = {hotfix_version}
|
1409
|
+
self.assertTrue(self.saasherder.validate_promotions())
|
1410
|
+
|
1411
|
+
|
1353
1412
|
def test_render_templated_parameters(
|
1354
1413
|
gql_class_factory: Callable[..., SaasFileInterface],
|
1355
1414
|
) -> None:
|
@@ -63,6 +63,9 @@ class SaasApp(Protocol):
|
|
63
63
|
@property
|
64
64
|
def service_owners(self) -> Optional[Sequence[SaasServiceOwner]]: ...
|
65
65
|
|
66
|
+
@property
|
67
|
+
def code_components(self) -> Optional[Sequence[AppCodeComponent]]: ...
|
68
|
+
|
66
69
|
|
67
70
|
class SaasPipelinesProvider(Protocol):
|
68
71
|
name: str
|
@@ -356,6 +359,11 @@ class SaasServiceOwner(Protocol):
|
|
356
359
|
email: str
|
357
360
|
|
358
361
|
|
362
|
+
class AppCodeComponent(Protocol):
|
363
|
+
url: str
|
364
|
+
hotfix_versions: Optional[list[str]]
|
365
|
+
|
366
|
+
|
359
367
|
SaasPipelinesProviders = Union[SaasPipelinesProviderTekton, SaasPipelinesProvider]
|
360
368
|
|
361
369
|
|
@@ -150,6 +150,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
150
150
|
self._promotion_state = PromotionState(state=state) if state else None
|
151
151
|
self._channel_map = self._assemble_channels(saas_files=all_saas_files)
|
152
152
|
self.images: set[str] = set()
|
153
|
+
self.hotfix_versions = self._collect_hotfix_versions()
|
153
154
|
|
154
155
|
# each namespace is in fact a target,
|
155
156
|
# so we can use it to calculate.
|
@@ -1057,6 +1058,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1057
1058
|
self._channel_map[sub] for sub in target.promotion.subscribe or []
|
1058
1059
|
]
|
1059
1060
|
target_promotion = Promotion(
|
1061
|
+
url=url,
|
1060
1062
|
auto=target.promotion.auto,
|
1061
1063
|
publish=target.promotion.publish,
|
1062
1064
|
subscribe=channels,
|
@@ -1098,6 +1100,14 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1098
1100
|
channel_map[publish].publisher_uids.append(publisher_uid)
|
1099
1101
|
return channel_map
|
1100
1102
|
|
1103
|
+
def _collect_hotfix_versions(self) -> dict[str, set[str]]:
|
1104
|
+
hotfix_versions: dict[str, set[str]] = {}
|
1105
|
+
for saas_file in self.saas_files:
|
1106
|
+
for cc in saas_file.app.code_components or []:
|
1107
|
+
for v in cc.hotfix_versions or []:
|
1108
|
+
hotfix_versions.setdefault(cc.url, set()).add(v)
|
1109
|
+
return hotfix_versions
|
1110
|
+
|
1101
1111
|
@staticmethod
|
1102
1112
|
def _collect_images(resource: Resource) -> set[str]:
|
1103
1113
|
images = set()
|
@@ -1889,6 +1899,10 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1889
1899
|
if not promotion.subscribe:
|
1890
1900
|
return True
|
1891
1901
|
|
1902
|
+
# hotfix must run before further gates are evaluated to override them
|
1903
|
+
if promotion.commit_sha in self.hotfix_versions.get(promotion.url, set()):
|
1904
|
+
return True
|
1905
|
+
|
1892
1906
|
now = datetime.now(timezone.utc)
|
1893
1907
|
passed_soak_days = timedelta(days=0)
|
1894
1908
|
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc877.dist-info → qontract_reconcile-0.10.1rc878.dist-info}/top_level.txt
RENAMED
File without changes
|