qontract-reconcile 0.10.1rc987__py3-none-any.whl → 0.10.1rc988__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.1rc987
3
+ Version: 0.10.1rc988
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
@@ -260,7 +260,7 @@ reconcile/gql_definitions/common/pgp_reencryption_settings.py,sha256=NPLmO6J-zSu
260
260
  reconcile/gql_definitions/common/pipeline_providers.py,sha256=JJgmmghqLIwjKOdcWYHPnf4PDgAq4GF7046i0ozrqgI,9127
261
261
  reconcile/gql_definitions/common/quay_instances.py,sha256=toBkdYYVTmEafezAHZKgaW-mQ29xEW6jeronzsAlNyI,1786
262
262
  reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
263
- reconcile/gql_definitions/common/saas_files.py,sha256=8JoysSi-lAjsdGKTK3YBTBPYy95B47guXzfp71JHh1I,16516
263
+ reconcile/gql_definitions/common/saas_files.py,sha256=O57zDNuEfW3MKWdqEjhHNIsvHmZdrQ9fn1TAeAcLivk,16594
264
264
  reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=4VYP2VbwY8WVwtSFk2-jsUNhSmRD3X4FWKxetOKvmd0,2835
265
265
  reconcile/gql_definitions/common/saasherder_settings.py,sha256=nqQLcMwYxLseqq0BEcVvmrpIj2eQq0h8XDSpLN6GGCw,1793
266
266
  reconcile/gql_definitions/common/slack_workspaces.py,sha256=2o0kgi4QiaRuNmZJnc_By4F6NsKIdRaXkrufRQw7Nok,1753
@@ -348,7 +348,6 @@ reconcile/gql_definitions/quay_membership/__init__.py,sha256=47DEQpj8HBSa-_TImW-
348
348
  reconcile/gql_definitions/quay_membership/quay_membership.py,sha256=H2xHvdNr3K0QzB2dituwStUIWCqePt35dkgeUZycECM,2824
349
349
  reconcile/gql_definitions/rhidp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
350
350
  reconcile/gql_definitions/rhidp/organizations.py,sha256=dW9y3ewFu3E-DFrZAi_SEewHYR0MWYeOB52vwnVcq5E,2580
351
- reconcile/gql_definitions/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
352
351
  reconcile/gql_definitions/service_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
353
352
  reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py,sha256=gEcYRrdhGKG83cOpGEnecE0mCxpQHLRzXFCp5FBIhLA,699
354
353
  reconcile/gql_definitions/service_dependencies/service_dependencies.py,sha256=CpMq9KjhFA61yniLo_11ypVInoeMBXbNmcY7_VAep-0,4700
@@ -433,7 +432,7 @@ reconcile/saas_auto_promotions_manager/integration.py,sha256=haXTpwi0rEQtN9-MadB
433
432
  reconcile/saas_auto_promotions_manager/meta.py,sha256=76Jp50r6Y_KyJoXFfSjrt5YrCtXyg_A4FXXxHYiS3TE,161
434
433
  reconcile/saas_auto_promotions_manager/publisher.py,sha256=IZGu-PMffyk3fNL8QcZ2VBmYTZ5zigoCwNJ4_Ak6-C8,2966
435
434
  reconcile/saas_auto_promotions_manager/s3_exporter.py,sha256=IKlVWZmiPnvl7sKeF6JgAlhXZe5CovKTxQc0SNkNSx4,2583
436
- reconcile/saas_auto_promotions_manager/subscriber.py,sha256=A-d_qIUo5jbseEaAN3YlVU46MQAVCw28j5HvORgaGtw,9149
435
+ reconcile/saas_auto_promotions_manager/subscriber.py,sha256=kIJKT1Xg5FF7EGT5ayK5ROyu_S7FbsYK91WBqrtYjfA,10030
437
436
  reconcile/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
438
437
  reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py,sha256=CP392gq0yntzEkqpMJl2j-N4CGfFDFbBfK77J7Oo5Pg,7817
439
438
  reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py,sha256=isY8frVsL3PlcdZmdZ4O0qyp76oczl4DUMX9uMArs5Y,1222
@@ -444,7 +443,7 @@ reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py,sha256
444
443
  reconcile/saas_auto_promotions_manager/merge_request_manager/open_merge_requests.py,sha256=-qGQOh6Jdp4lomNDij3zWVC0pl6uPHFWS5Woqcp5HQk,410
445
444
  reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=rnY9CR_0ONDJdJhGaGOQ9yBlKV0bPXQKh9Ped-NA2To,7245
446
445
  reconcile/saas_auto_promotions_manager/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
447
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=d0IiJ9q9XMCXumyKvUpvktS9ooSotPq3kggKw56V8tI,8618
446
+ reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=DZOT8jvM9tmLnipY884XN5T4ViJljAlcEz6XKdNCK5w,8860
448
447
  reconcile/skupper_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
449
448
  reconcile/skupper_network/integration.py,sha256=oZIVDBRcQPC-lWxNFiJhGbtCM7Yj7fjwAzYZ8JvVe3I,10789
450
449
  reconcile/skupper_network/models.py,sha256=HEwlVKsbmMaKaaBGvITIiSYNEVdjwXVhLaOJgLSZ2xQ,6604
@@ -541,7 +540,7 @@ reconcile/test/test_quay_repos.py,sha256=TdkcRF_a8PLp01Kti9eZZN-vGup2yPBT4Iba3k0
541
540
  reconcile/test/test_queries.py,sha256=SpH3RmNpBjEr_ne3VjAMCgKK8RE1z1zo7bypkT5uoO4,1946
542
541
  reconcile/test/test_repo_owners.py,sha256=uRYMLbMmh-9usF0TerabZTZV-Z1CS4I6ybT-LQqCLe8,1423
543
542
  reconcile/test/test_requests_sender.py,sha256=7fd9C2kEFS0-CYtlsif66N1kO9c44pzuBPAJKR9igqU,5385
544
- reconcile/test/test_saasherder.py,sha256=rGmN8t6gGfmpb4e_3gbfe74GNz8EERAosnrTsVo6ayo,57166
543
+ reconcile/test/test_saasherder.py,sha256=EMzqoAOFVbeFPuz4oG81srkuNfInHSu4smoArLheUa4,57234
545
544
  reconcile/test/test_saasherder_allowed_secret_paths.py,sha256=5NHQwNJO66at6HiyMZ5sVRTQDwxdvlOQo0KmkBWCw5Q,4853
546
545
  reconcile/test/test_secret_reader.py,sha256=kz7nzcPjvA08cytnvcA_PMA98AEyqJWsESkYeRn5xCk,4994
547
546
  reconcile/test/test_slack_base.py,sha256=pTUGvJ2S2wF3PhJyGWmiNXG52QtXKy2cbu-G8Ymrv6I,5019
@@ -566,7 +565,7 @@ reconcile/test/test_version_bump.py,sha256=q6-3Y1roriI6YWpFwaHOMN7emEP3yL33sh_0V
566
565
  reconcile/test/test_vpc_peerings_validator.py,sha256=dFSmjc_dMN2GqMbntCFpa7PUZmyYuQ9DKffh-T5wmxM,6639
567
566
  reconcile/test/test_wrong_region.py,sha256=7KzL7OaICQ9Z3DW27zt_ykMN7_87owAFC-2CYjvGoyA,2138
568
567
  reconcile/test/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
569
- reconcile/test/saas_auto_promotions_manager/conftest.py,sha256=tF6YMgeh9PHxlKsihL8qdLEgixk_k6mOGV1qS7ukHYI,6029
568
+ reconcile/test/saas_auto_promotions_manager/conftest.py,sha256=oRnwwFbL00TNwY1uacjPl0cwU3o064YpDhNkeoerGzE,6085
570
569
  reconcile/test/saas_auto_promotions_manager/test_integration_test.py,sha256=S30eXJSy2Vc3YLbCP7AfLkOiFGUVoKhEvEBL5vwnbfg,1848
571
570
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
572
571
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -851,8 +850,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
851
850
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
852
851
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
853
852
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
854
- qontract_reconcile-0.10.1rc987.dist-info/METADATA,sha256=GvWPOA4k5HVBOJq7UbGO7wBnbHV_RdoM8G3mhJzedQM,2262
855
- qontract_reconcile-0.10.1rc987.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
856
- qontract_reconcile-0.10.1rc987.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
857
- qontract_reconcile-0.10.1rc987.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
858
- qontract_reconcile-0.10.1rc987.dist-info/RECORD,,
853
+ qontract_reconcile-0.10.1rc988.dist-info/METADATA,sha256=wMWHbGMjtgHC7JAUM-MwuZiA9BoxXhp4qpYaj_fe-No,2262
854
+ qontract_reconcile-0.10.1rc988.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
855
+ qontract_reconcile-0.10.1rc988.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
856
+ qontract_reconcile-0.10.1rc988.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
857
+ qontract_reconcile-0.10.1rc988.dist-info/RECORD,,
@@ -265,6 +265,7 @@ query SaasFiles {
265
265
  publish
266
266
  subscribe
267
267
  soakDays
268
+ schedule
268
269
  promotion_data {
269
270
  channel
270
271
  data {
@@ -471,6 +472,7 @@ class SaasResourceTemplateTargetPromotionV1(ConfiguredBaseModel):
471
472
  publish: Optional[list[str]] = Field(..., alias="publish")
472
473
  subscribe: Optional[list[str]] = Field(..., alias="subscribe")
473
474
  soak_days: Optional[int] = Field(..., alias="soakDays")
475
+ schedule: Optional[str] = Field(..., alias="schedule")
474
476
  promotion_data: Optional[list[PromotionDataV1]] = Field(..., alias="promotion_data")
475
477
 
476
478
 
@@ -4,6 +4,8 @@ from collections.abc import Iterable
4
4
  from dataclasses import dataclass
5
5
  from datetime import UTC, datetime, timedelta
6
6
 
7
+ from croniter import croniter
8
+
7
9
  from reconcile.gql_definitions.fragments.saas_target_namespace import (
8
10
  SaasTargetNamespace,
9
11
  )
@@ -45,6 +47,7 @@ class Subscriber:
45
47
  uid: str,
46
48
  soak_days: int,
47
49
  blocked_versions: set[str],
50
+ schedule: str,
48
51
  ):
49
52
  self.saas_name = saas_name
50
53
  self.template_name = template_name
@@ -57,6 +60,7 @@ class Subscriber:
57
60
  self.target_namespace = target_namespace
58
61
  self.uid = uid
59
62
  self.soak_days = soak_days
63
+ self.schedule = schedule
60
64
  self._content_hash = ""
61
65
  self._use_target_config_hash = use_target_config_hash
62
66
  self._blocked_versions = blocked_versions
@@ -118,6 +122,17 @@ class Subscriber:
118
122
  delta += now - deployed_at
119
123
  return delta >= timedelta(days=self.soak_days)
120
124
 
125
+ def _is_valid_deployment_window(self) -> bool:
126
+ # Ideally we would catch that at schema validation time
127
+ if not croniter.is_valid(self.schedule):
128
+ logging.error(
129
+ "Subscriber at %s has an invalid schedule declaration %s. We will block any promotion for that target until this is fixed.",
130
+ self.target_file_path,
131
+ self.schedule,
132
+ )
133
+ return False
134
+ return croniter.match(self.schedule, datetime.now(UTC))
135
+
121
136
  def _compute_desired_ref(self) -> None:
122
137
  """
123
138
  Compute the desired reference for this subscriber.
@@ -168,6 +183,14 @@ class Subscriber:
168
183
  )
169
184
  return
170
185
 
186
+ if not self._is_valid_deployment_window():
187
+ logging.debug(
188
+ "Subscriber at path %s promotion stopped because we are not in the deployment window %s",
189
+ self.target_file_path,
190
+ self.schedule,
191
+ )
192
+ return
193
+
171
194
  desired_ref = next(iter(publisher_refs))
172
195
  if desired_ref in self._blocked_versions:
173
196
  logging.info(
@@ -102,6 +102,11 @@ class SaasFilesInventory:
102
102
  soak_days = (
103
103
  target.promotion.soak_days if target.promotion.soak_days else 0
104
104
  )
105
+ schedule = (
106
+ target.promotion.schedule
107
+ if target.promotion.schedule
108
+ else "* * * * *"
109
+ )
105
110
  subscriber = Subscriber(
106
111
  uid=target.uid(
107
112
  parent_saas_file_name=saas_file.name,
@@ -113,6 +118,7 @@ class SaasFilesInventory:
113
118
  ref=target.ref,
114
119
  target_namespace=target.namespace,
115
120
  soak_days=soak_days,
121
+ schedule=schedule,
116
122
  blocked_versions=blocked_versions.get(
117
123
  resource_template.url, set()
118
124
  ),
@@ -159,6 +159,7 @@ def subscriber_builder(
159
159
  use_target_config_hash=data.get("USE_TARGET_CONFIG_HASH", True),
160
160
  soak_days=data.get("SOAK_DAYS", 0),
161
161
  blocked_versions=data.get("BLOCKED_VERSIONS", {}),
162
+ schedule=data.get("SCHEDULE", "* * * * *"),
162
163
  )
163
164
  subscriber.channels = channels
164
165
  subscriber.config_hashes_by_channel_name = cur_config_hashes_by_channel
@@ -166,6 +166,7 @@ class TestSaasFileValid(TestCase):
166
166
  subscribe=None,
167
167
  promotion_data=None,
168
168
  soakDays=0,
169
+ schedule="* * * * *",
169
170
  )
170
171
  saasherder = SaasHerder(
171
172
  [self.saas_file],
@@ -190,6 +191,7 @@ class TestSaasFileValid(TestCase):
190
191
  subscribe=None,
191
192
  promotion_data=None,
192
193
  soakDays=0,
194
+ schedule="* * * * *",
193
195
  )
194
196
  saasherder = SaasHerder(
195
197
  [self.saas_file],