qontract-reconcile 0.10.1rc1178__py3-none-any.whl → 0.10.1rc1180__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.1rc1178
3
+ Version: 0.10.1rc1180
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
@@ -112,7 +112,7 @@ reconcile/terraform_aws_route53.py,sha256=dQzzT46YhwRA902_H6pi-f7WlX4EaH187wXSdm
112
112
  reconcile/terraform_cloudflare_dns.py,sha256=-aLEe2QnH5cJPu7HWqs-R9NmQ1NlFbcVUm0v7alVL3I,13431
113
113
  reconcile/terraform_cloudflare_resources.py,sha256=pq8Ieo5NmB-dYQ9X2F0s6iEoINMzhiqGw2yQK4ovok4,14980
114
114
  reconcile/terraform_cloudflare_users.py,sha256=iyTG5sj20Jg4J4qWJ144KVptfIHGOSfH8wQKxu0imq0,13942
115
- reconcile/terraform_repo.py,sha256=TKqlodhQGoAtQ6nDm04TNlpx4wpgJ_n4atoUK5Rfd7o,16444
115
+ reconcile/terraform_repo.py,sha256=jT8zD-V1_5D6yB2gLYP1nEC9wHoHktDQYnJqpo2EC9M,15807
116
116
  reconcile/terraform_resources.py,sha256=iufjMJs_aSEvmh7Cg11beCxKmV8nrOLOpEtiTryPNx0,19470
117
117
  reconcile/terraform_tgw_attachments.py,sha256=09svJG9pAiwWp4aY0xRoQRV90T4ZNwHG3r8flI-ZS_s,18810
118
118
  reconcile/terraform_users.py,sha256=HqSm3ev3b8dZ9J6F_phDZB-FQsnlsdeKp9RPoY1cU94,10188
@@ -397,7 +397,7 @@ reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.
397
397
  reconcile/gql_definitions/terraform_init/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
398
398
  reconcile/gql_definitions/terraform_init/aws_accounts.py,sha256=OJ0hDbRachRaDkL-OGT6-byr9cKdBiQDnNCpwUe3oJ8,2674
399
399
  reconcile/gql_definitions/terraform_repo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
400
- reconcile/gql_definitions/terraform_repo/terraform_repo.py,sha256=nm4CH7Vog4aabdvCKmhVSUvoUb7dxSLx8nwAEJAVqG0,3706
400
+ reconcile/gql_definitions/terraform_repo/terraform_repo.py,sha256=Eb6vb-nBIZMAiIbjTcDTH-eNv3831bvZAIgM6E287Hw,3861
401
401
  reconcile/gql_definitions/terraform_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
402
402
  reconcile/gql_definitions/terraform_resources/database_access_manager.py,sha256=yv0_YC-LmhaKD_gyGG3le1w5BtypBjlsO894-Zgdg4U,4813
403
403
  reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py,sha256=_man82NXH9Jw7OvgDiQCKiLDG6Q7aV_ktOAi12QCXbI,42793
@@ -566,7 +566,7 @@ reconcile/test/test_terraform_aws_route53.py,sha256=xHggb8K1P76OyCfFcogbkmyKle-N
566
566
  reconcile/test/test_terraform_cloudflare_dns.py,sha256=aQTXX8Vr4h9aWvJZTnpZEhMGYoBpT2d45ZxU_ECIQ6o,3425
567
567
  reconcile/test/test_terraform_cloudflare_resources.py,sha256=1mdSZS-38mtTSg7teJgDCJU1b_yKbwnrr3N5m8kwV4k,13595
568
568
  reconcile/test/test_terraform_cloudflare_users.py,sha256=2VGBtMUhckLPtUnQlHIzpGsCnyVJZPNLFf-ABELkxbQ,27456
569
- reconcile/test/test_terraform_repo.py,sha256=INfl-VlUtpV87J0neQt4wliptnX7PKvxLPF-ZgweTFA,12960
569
+ reconcile/test/test_terraform_repo.py,sha256=r6bwryHtq6-VuUh3fuMsxlsjbQAgrcQUHOEFou_hilQ,12260
570
570
  reconcile/test/test_terraform_resources.py,sha256=8C97yXIEihaQ3DZrtjxLNt4y4G12IOhD01ydm7JjliY,15359
571
571
  reconcile/test/test_terraform_tgw_attachments.py,sha256=pJFmQzUwAn-wKpF6oSkImpdF7WXvcky8iaJiXbjGGgU,41104
572
572
  reconcile/test/test_terraform_users.py,sha256=XOAfGvITCJPI1LTlISmHbA4ONMQMkxYUMTsny7pQCFw,4319
@@ -880,8 +880,8 @@ tools/test/test_qontract_cli.py,sha256=iuzKbQ6ahinvjoQmQLBrG4shey0z-1rB6qCgS8T6d
880
880
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
881
881
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
882
882
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
883
- qontract_reconcile-0.10.1rc1178.dist-info/METADATA,sha256=RfXebn7FPC9wsFLc2UmBeZ81WxuD2OpnNYVnkVAb7Fs,2213
884
- qontract_reconcile-0.10.1rc1178.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
885
- qontract_reconcile-0.10.1rc1178.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
886
- qontract_reconcile-0.10.1rc1178.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
887
- qontract_reconcile-0.10.1rc1178.dist-info/RECORD,,
883
+ qontract_reconcile-0.10.1rc1180.dist-info/METADATA,sha256=5FtpxYHIFj662mfS5_AXkrDYRFw4uWWBGxXElRlLS24,2213
884
+ qontract_reconcile-0.10.1rc1180.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
885
+ qontract_reconcile-0.10.1rc1180.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
886
+ qontract_reconcile-0.10.1rc1180.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
887
+ qontract_reconcile-0.10.1rc1180.dist-info/RECORD,,
@@ -47,6 +47,9 @@ query TerraformRepo {
47
47
  }
48
48
  }
49
49
  name
50
+ app {
51
+ name
52
+ }
50
53
  repository
51
54
  ref
52
55
  projectPath
@@ -92,6 +95,10 @@ class AWSAccountV1(ConfiguredBaseModel):
92
95
  terraform_state: Optional[TerraformStateAWSV1] = Field(..., alias="terraformState")
93
96
 
94
97
 
98
+ class AppV1(ConfiguredBaseModel):
99
+ name: str = Field(..., alias="name")
100
+
101
+
95
102
  class TerraformRepoVariablesV1(ConfiguredBaseModel):
96
103
  inputs: VaultSecret = Field(..., alias="inputs")
97
104
  outputs: VaultSecret = Field(..., alias="outputs")
@@ -100,6 +107,7 @@ class TerraformRepoVariablesV1(ConfiguredBaseModel):
100
107
  class TerraformRepoV1(ConfiguredBaseModel):
101
108
  account: AWSAccountV1 = Field(..., alias="account")
102
109
  name: str = Field(..., alias="name")
110
+ app: Optional[AppV1] = Field(..., alias="app")
103
111
  repository: str = Field(..., alias="repository")
104
112
  ref: str = Field(..., alias="ref")
105
113
  project_path: str = Field(..., alias="projectPath")
@@ -100,7 +100,6 @@ class TerraformRepoIntegration(
100
100
  desired_state=desired,
101
101
  dry_run=dry_run,
102
102
  state=state,
103
- recreate_state=False,
104
103
  )
105
104
 
106
105
  if repo_diff_result:
@@ -110,18 +109,19 @@ class TerraformRepoIntegration(
110
109
  # the existing state stored in S3. This is due to a behavior in Pydantic V1 that has since been addressed in V2
111
110
  # https://docs.pydantic.dev/latest/blog/pydantic-v2/#required-vs-nullable-cleanup
112
111
  # so in this case, tf-repo will just recreate all of those state files in S3 and not actually do a plan or apply
113
- logging.error(err)
114
- logging.info(
115
- "Unable to parse existing Terraform-Repo state from S3. Note that this is separate from the actual .tfstate files. Terraform Repo will re-create its own state upon merge and will not update any infrastructure. This typically occurs with changes to the Terraform Repo schema files and is normally resolved once state is re-created."
112
+ logging.warning(
113
+ "Unable to parse existing Terraform-Repo state from S3. Will re-create internal state upon apply, more info here: https://gitlab.cee.redhat.com/service/app-interface/-/blob/master/docs/terraform-repo/sop/statefile-load-errors.md",
114
+ exc_info=err,
116
115
  )
117
116
  repo_diff_result = self.calculate_diff(
118
117
  existing_state=[],
119
118
  desired_state=desired,
120
119
  dry_run=dry_run,
121
120
  state=state,
122
- recreate_state=True,
123
121
  )
124
122
 
123
+ # we don't call print_output here meaning that the executor will not plan/apply
124
+
125
125
  def print_output(self, diff: list[TerraformRepoV1], dry_run: bool) -> OutputFile:
126
126
  """Parses and prints the output of a Terraform Repo diff for the executor
127
127
 
@@ -302,7 +302,6 @@ class TerraformRepoIntegration(
302
302
  desired_state: list[TerraformRepoV1],
303
303
  dry_run: bool,
304
304
  state: State | None,
305
- recreate_state: bool,
306
305
  ) -> list[TerraformRepoV1] | None:
307
306
  """Calculated the difference between existing and desired state
308
307
  to determine what actions the executor will need to take
@@ -315,8 +314,6 @@ class TerraformRepoIntegration(
315
314
  :type dry_run: bool
316
315
  :param state: AWS S3 state
317
316
  :type state: Optional[State]
318
- :param recreate_state: whether we are recreating our own state
319
- :type recreate_state: bool
320
317
  :raises ParameterError: if there is an invalid operation performed like trying to delete
321
318
  a representation in A-I before setting the delete flag
322
319
  :return: the terraform repo to act on
@@ -326,13 +323,6 @@ class TerraformRepoIntegration(
326
323
 
327
324
  merged = self.merge_results(diff)
328
325
 
329
- # validate that only one repo is being modified in each MR
330
- # this lets us fail early and avoid multiple GL requests we don't need to make
331
- if dry_run and len(merged) > 1 and not recreate_state:
332
- raise Exception(
333
- "Only one repository can be modified per merge request, please split your change out into multiple MRs. Hint: try rebasing your merge request"
334
- )
335
-
336
326
  # added repos: do standard validation that SHA is valid
337
327
  if self.params.validate_git:
338
328
  for add_repo in diff.add.values():
@@ -42,6 +42,7 @@ def existing_repo(aws_account, tf_variables) -> TerraformRepoV1:
42
42
  repository=A_REPO,
43
43
  ref=A_REPO_SHA,
44
44
  account=aws_account,
45
+ app=None,
45
46
  projectPath="tf",
46
47
  delete=False,
47
48
  requireFips=True,
@@ -83,6 +84,7 @@ def new_repo(aws_account_no_state) -> TerraformRepoV1:
83
84
  repository=B_REPO,
84
85
  ref=B_REPO_SHA,
85
86
  account=aws_account_no_state,
87
+ app=None,
86
88
  projectPath="tf",
87
89
  delete=False,
88
90
  requireFips=False,
@@ -191,7 +193,6 @@ def test_addition_to_existing_repo(existing_repo, new_repo, int_params, state_mo
191
193
  desired_state=desired,
192
194
  dry_run=False,
193
195
  state=state_mock,
194
- recreate_state=False,
195
196
  )
196
197
 
197
198
  assert diff == [new_repo]
@@ -213,7 +214,6 @@ def test_updating_repo_ref(existing_repo, int_params, state_mock):
213
214
  desired_state=[updated_repo],
214
215
  dry_run=False,
215
216
  state=state_mock,
216
- recreate_state=False,
217
217
  )
218
218
 
219
219
  assert diff == [updated_repo]
@@ -234,7 +234,6 @@ def test_force_rerun(existing_repo, int_params, state_mock):
234
234
  desired_state=[updated_repo],
235
235
  dry_run=False,
236
236
  state=state_mock,
237
- recreate_state=False,
238
237
  )
239
238
 
240
239
  assert diff == [updated_repo]
@@ -261,7 +260,6 @@ def test_fail_on_update_invalid_repo_params(existing_repo, int_params):
261
260
  desired_state=[updated_repo],
262
261
  dry_run=True,
263
262
  state=None,
264
- recreate_state=False,
265
263
  )
266
264
 
267
265
 
@@ -277,7 +275,6 @@ def test_delete_repo(existing_repo, int_params, state_mock):
277
275
  desired_state=[updated_repo],
278
276
  dry_run=False,
279
277
  state=state_mock,
280
- recreate_state=False,
281
278
  )
282
279
 
283
280
  assert diff == [updated_repo]
@@ -296,7 +293,6 @@ def test_delete_repo_without_flag(existing_repo, int_params):
296
293
  desired_state=[],
297
294
  dry_run=True,
298
295
  state=None,
299
- recreate_state=False,
300
296
  )
301
297
 
302
298
 
@@ -316,6 +312,7 @@ def test_get_repo_state(s3_state_builder, int_params, existing_repo, tf_variable
316
312
  "tfVersion": A_REPO_VERSION,
317
313
  "variables": tf_variables,
318
314
  "forceRerunTimestamp": None,
315
+ "app": None,
319
316
  "account": {
320
317
  "name": "foo",
321
318
  "uid": AWS_UID,
@@ -358,7 +355,6 @@ def test_update_repo_state(int_params, existing_repo, state_mock):
358
355
  desired_state=desired_state,
359
356
  dry_run=False,
360
357
  state=state_mock,
361
- recreate_state=False,
362
358
  )
363
359
 
364
360
  state_mock.add.assert_called_once_with(
@@ -381,7 +377,6 @@ def test_output_correct_statefile(
381
377
  desired_state=desired_state,
382
378
  dry_run=True,
383
379
  state=state_mock,
384
- recreate_state=False,
385
380
  )
386
381
 
387
382
  assert diff
@@ -403,7 +398,6 @@ def test_output_correct_no_statefile(
403
398
  desired_state=desired_state,
404
399
  dry_run=True,
405
400
  state=state_mock,
406
- recreate_state=False,
407
401
  )
408
402
 
409
403
  assert diff
@@ -412,21 +406,6 @@ def test_output_correct_no_statefile(
412
406
  assert new_repo_output == current_output
413
407
 
414
408
 
415
- def test_fail_on_multiple_repos_dry_run(int_params, existing_repo, new_repo):
416
- integration = TerraformRepoIntegration(params=int_params)
417
-
418
- desired_state = [existing_repo, new_repo]
419
-
420
- with pytest.raises(Exception):
421
- integration.calculate_diff(
422
- existing_state=[],
423
- desired_state=desired_state,
424
- dry_run=True,
425
- state=None,
426
- recreate_state=False,
427
- )
428
-
429
-
430
409
  def test_succeed_on_multiple_repos_non_dry_run(int_params, existing_repo, new_repo):
431
410
  integration = TerraformRepoIntegration(params=int_params)
432
411
 
@@ -437,7 +416,6 @@ def test_succeed_on_multiple_repos_non_dry_run(int_params, existing_repo, new_re
437
416
  desired_state=desired_state,
438
417
  dry_run=False,
439
418
  state=None,
440
- recreate_state=False,
441
419
  )
442
420
 
443
421
  assert diff
@@ -457,7 +435,6 @@ def test_no_op_succeeds(int_params, existing_repo):
457
435
  desired_state=state,
458
436
  dry_run=True,
459
437
  state=None,
460
- recreate_state=False,
461
438
  )
462
439
 
463
440
  assert diff is None