qontract-reconcile 0.10.1rc1057__py3-none-any.whl → 0.10.1rc1059__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.1rc1057
3
+ Version: 0.10.1rc1059
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
@@ -114,7 +114,7 @@ reconcile/terraform_cloudflare_resources.py,sha256=41Mj1WkuS75slCDpmhG2GGf1nh3Bw
114
114
  reconcile/terraform_cloudflare_users.py,sha256=iyTG5sj20Jg4J4qWJ144KVptfIHGOSfH8wQKxu0imq0,13942
115
115
  reconcile/terraform_repo.py,sha256=TKqlodhQGoAtQ6nDm04TNlpx4wpgJ_n4atoUK5Rfd7o,16444
116
116
  reconcile/terraform_resources.py,sha256=-sgMMHDtNvnQyNR05-MKebI_pSiyxSWAg8LmeA2_Ntk,19326
117
- reconcile/terraform_tgw_attachments.py,sha256=EucuF4p3RWKTS4GTPd8oZmR79GpIW_grQl2PAeeNQeI,18665
117
+ reconcile/terraform_tgw_attachments.py,sha256=09svJG9pAiwWp4aY0xRoQRV90T4ZNwHG3r8flI-ZS_s,18810
118
118
  reconcile/terraform_users.py,sha256=HqSm3ev3b8dZ9J6F_phDZB-FQsnlsdeKp9RPoY1cU94,10188
119
119
  reconcile/terraform_vpc_peerings.py,sha256=VLSfuO7FvHN5McopRiKoKJDHCmIhYtlJEHv_hxV5kcM,27669
120
120
  reconcile/vault_replication.py,sha256=isfmNaqxl4AC90n8sVJffUt685sPBfhNSvjks6DoQXg,17339
@@ -255,7 +255,7 @@ reconcile/gql_definitions/common/aws_vpcs.py,sha256=Dss9dQ3xagnz3Ltg1e9mtG2PAmQG
255
255
  reconcile/gql_definitions/common/clusters.py,sha256=Dr5AsSsTuqjAxkI9fU0fdiaP6u5qkmRpkkCcYDnU584,21868
256
256
  reconcile/gql_definitions/common/clusters_minimal.py,sha256=JYrJV_aStmryiiGKyiXhj47qpF_8KilCqy-d9CofBCo,4635
257
257
  reconcile/gql_definitions/common/clusters_with_dms.py,sha256=GJ53P8tgMLh1NfVkaV9_AmaqF9pNUqJZcDkcKzKzUy0,2242
258
- reconcile/gql_definitions/common/clusters_with_peering.py,sha256=9NGjhJW_QWA5XSGGjULdIJdDVObdRqiX2OwEl9zTu4U,11838
258
+ reconcile/gql_definitions/common/clusters_with_peering.py,sha256=B1Hi3u6rZZsl4bDDPMLIcSRI5lNFuh29lPVVTOrRRpQ,11929
259
259
  reconcile/gql_definitions/common/github_orgs.py,sha256=rZ0pDAA2_9hF9N-ykRZIxPtEmczTSjuA_k3nkp0k1W0,2039
260
260
  reconcile/gql_definitions/common/jira_settings.py,sha256=Fmjxhlhr69kc4jkG_0k17fuYlQVucbNex0jXYu83wbY,1990
261
261
  reconcile/gql_definitions/common/jiralert_settings.py,sha256=H96nMg_r2YcOvioj3aIkwqtFrALGSLt7uhbx9jGSUTo,1984
@@ -566,7 +566,7 @@ reconcile/test/test_terraform_cloudflare_resources.py,sha256=1mdSZS-38mtTSg7teJg
566
566
  reconcile/test/test_terraform_cloudflare_users.py,sha256=2VGBtMUhckLPtUnQlHIzpGsCnyVJZPNLFf-ABELkxbQ,27456
567
567
  reconcile/test/test_terraform_repo.py,sha256=INfl-VlUtpV87J0neQt4wliptnX7PKvxLPF-ZgweTFA,12960
568
568
  reconcile/test/test_terraform_resources.py,sha256=8C97yXIEihaQ3DZrtjxLNt4y4G12IOhD01ydm7JjliY,15359
569
- reconcile/test/test_terraform_tgw_attachments.py,sha256=SM6QwogMZNLh0BkUyaxzFafuOLp23-hBtYTu_F53C4I,40922
569
+ reconcile/test/test_terraform_tgw_attachments.py,sha256=pJFmQzUwAn-wKpF6oSkImpdF7WXvcky8iaJiXbjGGgU,41104
570
570
  reconcile/test/test_terraform_users.py,sha256=XOAfGvITCJPI1LTlISmHbA4ONMQMkxYUMTsny7pQCFw,4319
571
571
  reconcile/test/test_terraform_vpc_peerings.py,sha256=bpjCjhmic07cw3XKSHf-2JvmLuWlyQG8laXlC-H7qtI,20796
572
572
  reconcile/test/test_terraform_vpc_peerings_build_desired_state.py,sha256=cHmr1_yhRgfdqlFX6TMw-aiKXebaRv0szl16M9YRJic,49988
@@ -724,8 +724,8 @@ reconcile/utils/sqs_gateway.py,sha256=XNIf3PY4UCPNufP2Ul0UJj3fKlt5larBba-VTT-41F
724
724
  reconcile/utils/state.py,sha256=W0_awkLAPX18hNOF_60o73tkPxDUylqbzYNHfl_sDsk,16386
725
725
  reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
726
726
  reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
727
- reconcile/utils/terraform_client.py,sha256=jHTkqqJk1HQh2vZP1FkEeDOiMlO-SKmX8oYuS7lzO_o,34672
728
- reconcile/utils/terrascript_aws_client.py,sha256=ctNT-TQSMxNicVIjR1gM2OZWzNc_BG820COSXb_E-CE,278933
727
+ reconcile/utils/terraform_client.py,sha256=rGyia1FuW-NtZhydreh5K2fAumvM9MJhxBaa6xUdH54,35905
728
+ reconcile/utils/terrascript_aws_client.py,sha256=SMsJaOmpn_9QQHhKIN_5ps1zOa9zEcBSsxGOyvF8voU,280492
729
729
  reconcile/utils/three_way_diff_strategy.py,sha256=oQcHXd9LVhirJfoaOBoHUYuZVGfyL2voKr6KVI34zZE,4833
730
730
  reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
731
731
  reconcile/utils/vault.py,sha256=9GSNHku8tw5KM2LKpZ1myWYDLtLGUJgpSnD0DxbzeO0,14956
@@ -867,8 +867,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
867
867
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
868
868
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
869
869
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
870
- qontract_reconcile-0.10.1rc1057.dist-info/METADATA,sha256=QAX2yVsbSHxtZT1eJKfc-v_ZDWOfcNA5gRNg4fHsgwo,2213
871
- qontract_reconcile-0.10.1rc1057.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
872
- qontract_reconcile-0.10.1rc1057.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
873
- qontract_reconcile-0.10.1rc1057.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
874
- qontract_reconcile-0.10.1rc1057.dist-info/RECORD,,
870
+ qontract_reconcile-0.10.1rc1059.dist-info/METADATA,sha256=YQ--_Q2We5-jBRDfo1Q4mpT0E9dwxpholocK39LiTCU,2213
871
+ qontract_reconcile-0.10.1rc1059.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
872
+ qontract_reconcile-0.10.1rc1059.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
873
+ qontract_reconcile-0.10.1rc1059.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
874
+ qontract_reconcile-0.10.1rc1059.dist-info/RECORD,,
@@ -147,6 +147,7 @@ query ClustersWithPeering {
147
147
  }
148
148
  tags
149
149
  cidrBlock
150
+ cidrBlocks
150
151
  manageSecurityGroups
151
152
  manageRoute53Associations
152
153
  allowPrivateHcpApiAccess
@@ -268,6 +269,7 @@ class ClusterPeeringConnectionAccountTGWV1(ClusterPeeringConnectionV1):
268
269
  account: ClusterPeeringConnectionAccountTGWV1_AWSAccountV1 = Field(..., alias="account")
269
270
  tags: Optional[Json] = Field(..., alias="tags")
270
271
  cidr_block: Optional[str] = Field(..., alias="cidrBlock")
272
+ cidr_blocks: Optional[list[str]] = Field(..., alias="cidrBlocks")
271
273
  manage_security_groups: Optional[bool] = Field(..., alias="manageSecurityGroups")
272
274
  manage_route53_associations: Optional[bool] = Field(..., alias="manageRoute53Associations")
273
275
  allow_private_hcp_api_access: Optional[bool] = Field(..., alias="allowPrivateHcpApiAccess")
@@ -64,11 +64,14 @@ class ValidationError(Exception):
64
64
  pass
65
65
 
66
66
 
67
- class AccountProviderInfo(BaseModel):
67
+ class TGWAccountProviderInfo(BaseModel):
68
68
  name: str
69
69
  uid: str
70
70
  assume_role: str | None
71
71
  assume_region: str
72
+
73
+
74
+ class ClusterAccountProviderInfo(TGWAccountProviderInfo):
72
75
  assume_cidr: str
73
76
 
74
77
 
@@ -79,8 +82,9 @@ class Requester(BaseModel):
79
82
  routes: list[dict] | None
80
83
  rules: list[dict] | None
81
84
  hostedzones: list[str] | None
82
- cidr_block: str
83
- account: AccountProviderInfo
85
+ cidr_block: str | None
86
+ cidr_blocks: list[str]
87
+ account: TGWAccountProviderInfo
84
88
 
85
89
 
86
90
  class Accepter(BaseModel):
@@ -89,7 +93,7 @@ class Accepter(BaseModel):
89
93
  vpc_id: str | None
90
94
  route_table_ids: list[str] | None
91
95
  subnets_id_az: list[dict] | None
92
- account: AccountProviderInfo
96
+ account: ClusterAccountProviderInfo
93
97
  api_security_group_id: str | None
94
98
 
95
99
 
@@ -225,7 +229,7 @@ def _build_account_with_assume_role(
225
229
  region: str,
226
230
  cidr_block: str,
227
231
  ocm: OCM | None,
228
- ) -> AccountProviderInfo:
232
+ ) -> ClusterAccountProviderInfo:
229
233
  account = peer_connection.account
230
234
  # assume_role is the role to assume to provision the
231
235
  # peering connection request, through the accepter AWS account.
@@ -235,7 +239,7 @@ def _build_account_with_assume_role(
235
239
  # there is no OCM at all.
236
240
  if not assume_role:
237
241
  if isinstance(cluster.spec, ClusterSpecROSAV1) and cluster.spec.account:
238
- return AccountProviderInfo(
242
+ return ClusterAccountProviderInfo(
239
243
  name=cluster.spec.account.name,
240
244
  uid=cluster.spec.account.uid,
241
245
  assume_role=assume_role,
@@ -247,7 +251,7 @@ def _build_account_with_assume_role(
247
251
  assume_role = ocm.get_aws_infrastructure_access_terraform_assume_role(
248
252
  cluster.name, account.uid, account.terraform_username
249
253
  )
250
- return AccountProviderInfo(
254
+ return ClusterAccountProviderInfo(
251
255
  name=account.name,
252
256
  uid=account.uid,
253
257
  assume_role=assume_role,
@@ -258,7 +262,7 @@ def _build_account_with_assume_role(
258
262
 
259
263
  def _build_accepter(
260
264
  peer_connection: ClusterPeeringConnectionAccountTGWV1,
261
- account: AccountProviderInfo,
265
+ account: ClusterAccountProviderInfo,
262
266
  region: str,
263
267
  cidr_block: str,
264
268
  awsapi: AWSApi,
@@ -290,11 +294,10 @@ def _build_requester(
290
294
  peer_connection: ClusterPeeringConnectionAccountTGWV1,
291
295
  tgw: Mapping,
292
296
  ) -> Requester:
293
- tgw_account = AccountProviderInfo(
297
+ tgw_account = TGWAccountProviderInfo(
294
298
  name=peer_connection.account.name,
295
299
  uid=peer_connection.account.uid,
296
300
  assume_region=tgw["region"],
297
- assume_cidr=peer_connection.cidr_block,
298
301
  )
299
302
  return Requester(
300
303
  tgw_id=tgw["tgw_id"],
@@ -304,6 +307,7 @@ def _build_requester(
304
307
  rules=tgw.get("rules"),
305
308
  hostedzones=tgw.get("hostedzones"),
306
309
  cidr_block=peer_connection.cidr_block,
310
+ cidr_blocks=peer_connection.cidr_blocks or [],
307
311
  account=tgw_account,
308
312
  )
309
313
 
@@ -161,6 +161,7 @@ def peering_connection_builder(
161
161
  account: ClusterPeeringConnectionAccountTGWV1_AWSAccountV1 | None = None,
162
162
  assume_role: str | None = None,
163
163
  cidr_block: str | None = None,
164
+ cidr_blocks: list[str] | None = None,
164
165
  delete: bool | None = None,
165
166
  ) -> ClusterPeeringConnectionAccountTGWV1:
166
167
  return gql_class_factory(
@@ -172,6 +173,7 @@ def peering_connection_builder(
172
173
  "account": account.dict(by_alias=True) if account is not None else None,
173
174
  "assumeRole": assume_role,
174
175
  "cidrBlock": cidr_block,
176
+ "cidrBlocks": cidr_blocks,
175
177
  "delete": delete,
176
178
  },
177
179
  )
@@ -191,6 +193,7 @@ def account_tgw_connection(
191
193
  account=tgw_connection_account,
192
194
  assume_role=None,
193
195
  cidr_block="172.16.0.0/16",
196
+ cidr_blocks=["10.240.0.0/12"],
194
197
  delete=False,
195
198
  )
196
199
 
@@ -481,6 +484,7 @@ def build_expected_desired_state_item(
481
484
  rules=tgw["rules"],
482
485
  hostedzones=tgw["hostedzones"],
483
486
  cidr_block=connection.cidr_block,
487
+ cidr_blocks=connection.cidr_blocks or [],
484
488
  account=expected_tgw_account,
485
489
  ),
486
490
  accepter=Accepter(
@@ -331,12 +331,27 @@ class TerraformClient: # pylint: disable=too-many-public-methods
331
331
  for resource_change in resource_changes:
332
332
  resource_type = resource_change["type"]
333
333
  resource_name = resource_change["name"]
334
+ resource_previous_address = resource_change.get("previous_address")
334
335
  resource_change = resource_change["change"]
335
336
  actions = resource_change["actions"]
336
337
  for action in actions:
338
+ if resource_previous_address:
339
+ # the resource is being moved/renamed in the TF state
340
+ with self._log_lock:
341
+ logging.info([
342
+ "move/rename",
343
+ name,
344
+ resource_previous_address,
345
+ resource_change["address"],
346
+ ])
347
+
337
348
  if action == "no-op":
338
349
  logging.debug([action, name, resource_type, resource_name])
339
- continue
350
+ if resource_previous_address:
351
+ # apply resource renaming with no-op
352
+ self.increment_apply_count()
353
+ else:
354
+ continue
340
355
  if action == "update" and resource_type == "aws_db_instance":
341
356
  self.validate_db_upgrade(name, resource_name, resource_change)
342
357
  # Ignore RDS modifications that are going to occur during the next
@@ -790,6 +805,9 @@ class TerraformClient: # pylint: disable=too-many-public-methods
790
805
 
791
806
  blue_green_update = after.get("blue_green_update", [])
792
807
  if blue_green_update and blue_green_update[0]["enabled"]:
808
+ changed_fields = self._resource_diff_changed_fields(
809
+ "update", resource_change
810
+ )
793
811
  replica = before["replicas"] != [] or before["replicate_source_db"]
794
812
  self.validate_blue_green_update_requirements(
795
813
  account_name,
@@ -799,6 +817,7 @@ class TerraformClient: # pylint: disable=too-many-public-methods
799
817
  replica,
800
818
  before["parameter_group_name"],
801
819
  region_name,
820
+ changed_fields=changed_fields,
802
821
  )
803
822
 
804
823
  def validate_blue_green_update_requirements(
@@ -810,6 +829,7 @@ class TerraformClient: # pylint: disable=too-many-public-methods
810
829
  replica: bool,
811
830
  parameter_group: str,
812
831
  region_name: str,
832
+ changed_fields: set[str],
813
833
  ) -> None:
814
834
  min_supported_versions = {
815
835
  "mysql": [pkg_version.parse("5.7"), pkg_version.parse("8.0.15")],
@@ -862,6 +882,13 @@ class TerraformClient: # pylint: disable=too-many-public-methods
862
882
  )
863
883
  return
864
884
 
885
+ if "storage_type" in changed_fields or "allocated_storage" in changed_fields:
886
+ logging.error(
887
+ f"Cannot upgrade RDS instance: {resource_name}. "
888
+ f"Blue/green updates are not supported when 'storage_type' or 'allocated_storage' has changed."
889
+ )
890
+ return
891
+
865
892
 
866
893
  class TerraformPlanFailed(Exception):
867
894
  pass
@@ -35,6 +35,7 @@ from sretoolbox.utils import threaded
35
35
  # temporary to create aws_ecrpublic_repository
36
36
  from terrascript import (
37
37
  Backend,
38
+ Block,
38
39
  Data,
39
40
  Module,
40
41
  Output,
@@ -299,6 +300,13 @@ class UnapprovedSecretPathError(Exception):
299
300
  pass
300
301
 
301
302
 
303
+ class Moved(Block):
304
+ """Terraform `moved` block, available since Terraform 1.1"""
305
+
306
+ def __init__(self, fro: str, to: str):
307
+ super().__init__(fro=fro, to=to)
308
+
309
+
302
310
  class aws_ecrpublic_repository(Resource):
303
311
  pass
304
312
 
@@ -1392,17 +1400,32 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
1392
1400
  # add routes to existing route tables
1393
1401
  route_table_ids = accepter.route_table_ids
1394
1402
  req_cidr_block = requester.cidr_block
1395
- if route_table_ids and req_cidr_block:
1403
+ req_cidr_blocks = requester.cidr_blocks or []
1404
+ if req_cidr_block:
1405
+ req_cidr_blocks.append(req_cidr_block)
1406
+ if route_table_ids and (req_cidr_block or req_cidr_blocks):
1396
1407
  for route_table_id in route_table_ids:
1397
- values = {
1398
- "provider": "aws." + acc_alias,
1399
- "route_table_id": route_table_id,
1400
- "destination_cidr_block": req_cidr_block,
1401
- "transit_gateway_id": requester.tgw_id,
1402
- }
1403
- route_identifier = f"{identifier}-{route_table_id}"
1404
- tf_resource = aws_route(route_identifier, **values)
1405
- self.add_resource(infra_account_name, tf_resource)
1408
+ for cidr_block in req_cidr_blocks:
1409
+ values = {
1410
+ "provider": "aws." + acc_alias,
1411
+ "route_table_id": route_table_id,
1412
+ "destination_cidr_block": cidr_block,
1413
+ "transit_gateway_id": requester.tgw_id,
1414
+ }
1415
+ # use the cidr block in the resource name to allow re-ordering
1416
+ cidr_id = cidr_block.replace(".", "-").replace("/", "_")
1417
+ route_identifier = (
1418
+ f"{identifier}-{route_table_id}-dest-{cidr_id}"
1419
+ )
1420
+ tf_resource = aws_route(route_identifier, **values)
1421
+ self.add_resource(infra_account_name, tf_resource)
1422
+ if req_cidr_block:
1423
+ req_cidr_id = req_cidr_block.replace(".", "-").replace("/", "_")
1424
+ moved = Moved(
1425
+ fro=f"aws_route.{identifier}-{route_table_id}",
1426
+ to=f"aws_route.{identifier}-{route_table_id}-dest-{req_cidr_id}",
1427
+ )
1428
+ self.add_moved(infra_account_name, moved)
1406
1429
 
1407
1430
  # add routes to peered transit gateways in the requester's
1408
1431
  # account to achieve global routing from all regions
@@ -4084,6 +4107,19 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
4084
4107
  with self.locks[account]:
4085
4108
  self.tss[account].add(tf_resource)
4086
4109
 
4110
+ def add_moved(self, account: str, moved: Moved):
4111
+ if account not in self.locks:
4112
+ logging.debug(
4113
+ f"integration {self.integration} is disabled for account {account}. "
4114
+ "can not add resource"
4115
+ )
4116
+ return
4117
+ with self.locks[account]:
4118
+ self.tss[account].setdefault("moved", []).append({
4119
+ "from": moved.fro,
4120
+ "to": moved.to,
4121
+ })
4122
+
4087
4123
  def dump(
4088
4124
  self,
4089
4125
  print_to_file: str | None = None,