qontract-reconcile 0.10.2.dev41__py3-none-any.whl → 0.10.2.dev43__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.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev41
3
+ Version: 0.10.2.dev43
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
6
6
  Project-URL: repository, https://github.com/app-sre/qontract-reconcile
@@ -215,7 +215,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=BgMx-NyV9mTuv7Sotb2OioC
215
215
  reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
216
216
  reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
217
217
  reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
- reconcile/gql_definitions/introspection.json,sha256=ErIjLKDbNw4SLyGXhp9iGmL1RSfT0U7gU1A3tsn1674,2217790
218
+ reconcile/gql_definitions/introspection.json,sha256=6e7VKZ_Ds1-fNKLF8Jf3yOHZ0SiIeYhAY277cpSoPdE,2235110
219
219
  reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
220
220
  reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
221
221
  reconcile/gql_definitions/acs/acs_policies.py,sha256=bN5i4mks10Z23KJSj7jqp966Osq2dps4d-sPH9gjxEA,7008
@@ -279,7 +279,7 @@ reconcile/gql_definitions/common/pipeline_providers.py,sha256=9rpsqPuvj82B4ki56x
279
279
  reconcile/gql_definitions/common/quay_instances.py,sha256=toBkdYYVTmEafezAHZKgaW-mQ29xEW6jeronzsAlNyI,1786
280
280
  reconcile/gql_definitions/common/quay_orgs.py,sha256=NhA8kqvVUDbrsryEvEL5mlIv5R3T4XNhSRXtfL_yptY,1788
281
281
  reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
282
- reconcile/gql_definitions/common/saas_files.py,sha256=i0U0Ot4DwE3LjigD4ex_ASOPWfSZEpX_4ZrRaWlUhW8,16854
282
+ reconcile/gql_definitions/common/saas_files.py,sha256=Z_ESsBaZVfSyCYN9RrNaOAQyUll6Cgh7hHGQcTPkenY,17792
283
283
  reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=4VYP2VbwY8WVwtSFk2-jsUNhSmRD3X4FWKxetOKvmd0,2835
284
284
  reconcile/gql_definitions/common/saasherder_settings.py,sha256=nqQLcMwYxLseqq0BEcVvmrpIj2eQq0h8XDSpLN6GGCw,1793
285
285
  reconcile/gql_definitions/common/slack_workspaces.py,sha256=2o0kgi4QiaRuNmZJnc_By4F6NsKIdRaXkrufRQw7Nok,1753
@@ -537,7 +537,7 @@ reconcile/typed_queries/pagerduty_instances.py,sha256=zxCNxMak4iikryePaRi71lTADV
537
537
  reconcile/typed_queries/quay.py,sha256=3IMy9jjHF2f9t47EXZOQVA3p0nFkWFhaFhxhvib-71o,644
538
538
  reconcile/typed_queries/repos.py,sha256=8A93dKDt6igT4ClqMjt7YUTsoP4qh1Wnm0W3xsMgj48,824
539
539
  reconcile/typed_queries/reserved_networks.py,sha256=XY9y3amtIQT0n06O0Toubqr_UmylJ2ELAv9-BJCK890,345
540
- reconcile/typed_queries/saas_files.py,sha256=MdU-D4a8JpJ8FDRVOCy1Bkf26qpdH-7sXY2W6eWdAWw,13993
540
+ reconcile/typed_queries/saas_files.py,sha256=JTs865Bqt4KuVh-_ze8IKLe_V1RRBnR7w2nveaUXXLw,14194
541
541
  reconcile/typed_queries/slack.py,sha256=r30lspctHloyygPn8_DVybxPwUWwiBpvBRRXiTVcQYk,251
542
542
  reconcile/typed_queries/slo_documents.py,sha256=YMdox_-lBRqrdxamPhdnUlRTY_Ro35ptsupq7OaynUQ,362
543
543
  reconcile/typed_queries/smtp.py,sha256=aSLglYa5bHKmlGwKkxq2RZqyMWuAf0a4S_mOuhDa084,542
@@ -633,7 +633,7 @@ reconcile/utils/state.py,sha256=az4tBmZ0EdbFcAGiBVUxs3cr2-BVWsuDQiNTvjjQq8s,1637
633
633
  reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
634
634
  reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
635
635
  reconcile/utils/terraform_client.py,sha256=H8frsS370y8xfivKLNBD1dwlBLHvfuR6JSN_syBL5Qc,36033
636
- reconcile/utils/terrascript_aws_client.py,sha256=UdEM3JeTMiE0VRqtz7gcBWR-c0fouORtPFrniRJ3pao,283505
636
+ reconcile/utils/terrascript_aws_client.py,sha256=SNGtsG1n-IDZaI0blKLm3t3AfVNmxW-O8Y8NtX08OOc,270318
637
637
  reconcile/utils/three_way_diff_strategy.py,sha256=oQcHXd9LVhirJfoaOBoHUYuZVGfyL2voKr6KVI34zZE,4833
638
638
  reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
639
639
  reconcile/utils/vault.py,sha256=aSA8l9cJlPUHpChFGl27nSY-Mpq9FMjBo7Dcgb1BVfM,15036
@@ -725,9 +725,9 @@ reconcile/utils/runtime/meta.py,sha256=dWdKS9eHVuowFkTK4lgXJ723vS1y9giOMzePUKnHn
725
725
  reconcile/utils/runtime/runner.py,sha256=I30KRrX1UQbHc_Ir1cIZX3OfNSdoHKdnDSPAEB69Ilk,7944
726
726
  reconcile/utils/runtime/sharding.py,sha256=r0ieUtNed7NvknSw6qQrCkKpVXE1shuHGnfFcnpA_k4,16142
727
727
  reconcile/utils/saasherder/__init__.py,sha256=3U8plqMAPRE1kjwZ5YnIsYsggTf4_gS7flRUEuXVBAs,343
728
- reconcile/utils/saasherder/interfaces.py,sha256=C2wrw34OXypshVocAsPrVZsSHptgw4g9u7Haa2wulZQ,9087
729
- reconcile/utils/saasherder/models.py,sha256=z8ln03zi2a8cu716NcNUDHp8Dv1VcVbhqdWVxCl7x9A,10148
730
- reconcile/utils/saasherder/saasherder.py,sha256=TP33j32cZA3-QdkG1i4wTUyWf9X1tiGoT0_5YNo2K98,86338
728
+ reconcile/utils/saasherder/interfaces.py,sha256=M9NG3tFDMdd4t44NTGwDqpiZ-Tt0qMEsXiqsYszXbT4,9180
729
+ reconcile/utils/saasherder/models.py,sha256=JaOz_DEtudJZhiDe90kaBlJkppFufn81V92oK9PHYx0,10208
730
+ reconcile/utils/saasherder/saasherder.py,sha256=1H6ZpyveYiqTrggsQT4LvWd1J0vacbFV6_iSjjnlQ6k,87144
731
731
  reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
732
732
  reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
733
733
  reconcile/utils/terraform/config_client.py,sha256=gRL1rQ0AqvShei_rcGqC3HDYGskOFKE1nPrJyJE9yno,4676
@@ -773,7 +773,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
773
773
  tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
774
774
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
775
775
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
776
- qontract_reconcile-0.10.2.dev41.dist-info/METADATA,sha256=8PiKTa5Okn_uKzxrj2VGYxeESqL-AQxMfyTWp7ivUgo,24665
777
- qontract_reconcile-0.10.2.dev41.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
778
- qontract_reconcile-0.10.2.dev41.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
779
- qontract_reconcile-0.10.2.dev41.dist-info/RECORD,,
776
+ qontract_reconcile-0.10.2.dev43.dist-info/METADATA,sha256=dR0wcgtr249AUyR4Ry3LQDzF8VgP0FQO4AEs_sCbJLM,24665
777
+ qontract_reconcile-0.10.2.dev43.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
778
+ qontract_reconcile-0.10.2.dev43.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
779
+ qontract_reconcile-0.10.2.dev43.dist-info/RECORD,,
@@ -302,6 +302,15 @@ query SaasFiles {
302
302
  }
303
303
  name
304
304
  }
305
+ images {
306
+ org {
307
+ name
308
+ instance {
309
+ url
310
+ }
311
+ }
312
+ name
313
+ }
305
314
  disable
306
315
  delete
307
316
  }
@@ -508,6 +517,20 @@ class SaasResourceTemplateTargetImageV1(ConfiguredBaseModel):
508
517
  name: str = Field(..., alias="name")
509
518
 
510
519
 
520
+ class SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1_QuayOrgV1_QuayInstanceV1(ConfiguredBaseModel):
521
+ url: str = Field(..., alias="url")
522
+
523
+
524
+ class SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1_QuayOrgV1(ConfiguredBaseModel):
525
+ name: str = Field(..., alias="name")
526
+ instance: SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1_QuayOrgV1_QuayInstanceV1 = Field(..., alias="instance")
527
+
528
+
529
+ class SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1(ConfiguredBaseModel):
530
+ org: SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1_QuayOrgV1 = Field(..., alias="org")
531
+ name: str = Field(..., alias="name")
532
+
533
+
511
534
  class SaasResourceTemplateTargetV2(ConfiguredBaseModel):
512
535
  path: Optional[str] = Field(..., alias="path")
513
536
  name: Optional[str] = Field(..., alias="name")
@@ -520,6 +543,7 @@ class SaasResourceTemplateTargetV2(ConfiguredBaseModel):
520
543
  secret_parameters: Optional[list[SaasResourceTemplateTargetV2_SaasSecretParametersV1]] = Field(..., alias="secretParameters")
521
544
  upstream: Optional[SaasResourceTemplateTargetUpstreamV1] = Field(..., alias="upstream")
522
545
  image: Optional[SaasResourceTemplateTargetImageV1] = Field(..., alias="image")
546
+ images: Optional[list[SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1]] = Field(..., alias="images")
523
547
  disable: Optional[bool] = Field(..., alias="disable")
524
548
  delete: Optional[bool] = Field(..., alias="delete")
525
549
 
@@ -3755,6 +3755,57 @@
3755
3755
  },
3756
3756
  "isDeprecated": false,
3757
3757
  "deprecationReason": null
3758
+ },
3759
+ {
3760
+ "name": "managed_dynatrace_token_provider_labels_v1",
3761
+ "description": null,
3762
+ "args": [
3763
+ {
3764
+ "name": "name",
3765
+ "description": null,
3766
+ "type": {
3767
+ "kind": "SCALAR",
3768
+ "name": "String",
3769
+ "ofType": null
3770
+ },
3771
+ "defaultValue": null
3772
+ },
3773
+ {
3774
+ "name": "path",
3775
+ "description": null,
3776
+ "type": {
3777
+ "kind": "SCALAR",
3778
+ "name": "String",
3779
+ "ofType": null
3780
+ },
3781
+ "defaultValue": null
3782
+ },
3783
+ {
3784
+ "name": "filter",
3785
+ "description": null,
3786
+ "type": {
3787
+ "kind": "SCALAR",
3788
+ "name": "JSON",
3789
+ "ofType": null
3790
+ },
3791
+ "defaultValue": null
3792
+ }
3793
+ ],
3794
+ "type": {
3795
+ "kind": "LIST",
3796
+ "name": null,
3797
+ "ofType": {
3798
+ "kind": "NON_NULL",
3799
+ "name": null,
3800
+ "ofType": {
3801
+ "kind": "OBJECT",
3802
+ "name": "ManagedDynatraceTokenProviderLabels_v1",
3803
+ "ofType": null
3804
+ }
3805
+ }
3806
+ },
3807
+ "isDeprecated": false,
3808
+ "deprecationReason": null
3758
3809
  }
3759
3810
  ],
3760
3811
  "inputFields": null,
@@ -5568,6 +5619,11 @@
5568
5619
  "name": "AppChangelog_v1",
5569
5620
  "ofType": null
5570
5621
  },
5622
+ {
5623
+ "kind": "OBJECT",
5624
+ "name": "ManagedDynatraceTokenProviderLabels_v1",
5625
+ "ofType": null
5626
+ },
5571
5627
  {
5572
5628
  "kind": "OBJECT",
5573
5629
  "name": "DatabaseAccess_v1",
@@ -22295,6 +22351,26 @@
22295
22351
  "isDeprecated": false,
22296
22352
  "deprecationReason": null
22297
22353
  },
22354
+ {
22355
+ "name": "images",
22356
+ "description": null,
22357
+ "args": [],
22358
+ "type": {
22359
+ "kind": "LIST",
22360
+ "name": null,
22361
+ "ofType": {
22362
+ "kind": "NON_NULL",
22363
+ "name": null,
22364
+ "ofType": {
22365
+ "kind": "OBJECT",
22366
+ "name": "SaasResourceTemplateTargetImage_v1",
22367
+ "ofType": null
22368
+ }
22369
+ }
22370
+ },
22371
+ "isDeprecated": false,
22372
+ "deprecationReason": null
22373
+ },
22298
22374
  {
22299
22375
  "name": "image",
22300
22376
  "description": null,
@@ -34204,6 +34280,249 @@
34204
34280
  "enumValues": null,
34205
34281
  "possibleTypes": null
34206
34282
  },
34283
+ {
34284
+ "kind": "OBJECT",
34285
+ "name": "ManagedDynatraceTokenProviderLabels_v1",
34286
+ "description": null,
34287
+ "fields": [
34288
+ {
34289
+ "name": "schema",
34290
+ "description": null,
34291
+ "args": [],
34292
+ "type": {
34293
+ "kind": "NON_NULL",
34294
+ "name": null,
34295
+ "ofType": {
34296
+ "kind": "SCALAR",
34297
+ "name": "String",
34298
+ "ofType": null
34299
+ }
34300
+ },
34301
+ "isDeprecated": false,
34302
+ "deprecationReason": null
34303
+ },
34304
+ {
34305
+ "name": "path",
34306
+ "description": null,
34307
+ "args": [],
34308
+ "type": {
34309
+ "kind": "NON_NULL",
34310
+ "name": null,
34311
+ "ofType": {
34312
+ "kind": "SCALAR",
34313
+ "name": "String",
34314
+ "ofType": null
34315
+ }
34316
+ },
34317
+ "isDeprecated": false,
34318
+ "deprecationReason": null
34319
+ },
34320
+ {
34321
+ "name": "name",
34322
+ "description": null,
34323
+ "args": [],
34324
+ "type": {
34325
+ "kind": "NON_NULL",
34326
+ "name": null,
34327
+ "ofType": {
34328
+ "kind": "SCALAR",
34329
+ "name": "String",
34330
+ "ofType": null
34331
+ }
34332
+ },
34333
+ "isDeprecated": false,
34334
+ "deprecationReason": null
34335
+ },
34336
+ {
34337
+ "name": "description",
34338
+ "description": null,
34339
+ "args": [],
34340
+ "type": {
34341
+ "kind": "SCALAR",
34342
+ "name": "String",
34343
+ "ofType": null
34344
+ },
34345
+ "isDeprecated": false,
34346
+ "deprecationReason": null
34347
+ },
34348
+ {
34349
+ "name": "ocm",
34350
+ "description": null,
34351
+ "args": [],
34352
+ "type": {
34353
+ "kind": "NON_NULL",
34354
+ "name": null,
34355
+ "ofType": {
34356
+ "kind": "OBJECT",
34357
+ "name": "OpenShiftClusterManager_v1",
34358
+ "ofType": null
34359
+ }
34360
+ },
34361
+ "isDeprecated": false,
34362
+ "deprecationReason": null
34363
+ },
34364
+ {
34365
+ "name": "labelDefaults",
34366
+ "description": null,
34367
+ "args": [],
34368
+ "type": {
34369
+ "kind": "NON_NULL",
34370
+ "name": null,
34371
+ "ofType": {
34372
+ "kind": "LIST",
34373
+ "name": null,
34374
+ "ofType": {
34375
+ "kind": "NON_NULL",
34376
+ "name": null,
34377
+ "ofType": {
34378
+ "kind": "OBJECT",
34379
+ "name": "DynatraceTokenProviderLabelDefault_v1",
34380
+ "ofType": null
34381
+ }
34382
+ }
34383
+ }
34384
+ },
34385
+ "isDeprecated": false,
34386
+ "deprecationReason": null
34387
+ },
34388
+ {
34389
+ "name": "clusters",
34390
+ "description": null,
34391
+ "args": [],
34392
+ "type": {
34393
+ "kind": "NON_NULL",
34394
+ "name": null,
34395
+ "ofType": {
34396
+ "kind": "LIST",
34397
+ "name": null,
34398
+ "ofType": {
34399
+ "kind": "NON_NULL",
34400
+ "name": null,
34401
+ "ofType": {
34402
+ "kind": "OBJECT",
34403
+ "name": "OpenShiftClusterManagerUpgradePolicyCluster_v1",
34404
+ "ofType": null
34405
+ }
34406
+ }
34407
+ }
34408
+ },
34409
+ "isDeprecated": false,
34410
+ "deprecationReason": null
34411
+ }
34412
+ ],
34413
+ "inputFields": null,
34414
+ "interfaces": [
34415
+ {
34416
+ "kind": "INTERFACE",
34417
+ "name": "DatafileObject_v1",
34418
+ "ofType": null
34419
+ }
34420
+ ],
34421
+ "enumValues": null,
34422
+ "possibleTypes": null
34423
+ },
34424
+ {
34425
+ "kind": "OBJECT",
34426
+ "name": "DynatraceTokenProviderLabelDefault_v1",
34427
+ "description": null,
34428
+ "fields": [
34429
+ {
34430
+ "name": "name",
34431
+ "description": null,
34432
+ "args": [],
34433
+ "type": {
34434
+ "kind": "NON_NULL",
34435
+ "name": null,
34436
+ "ofType": {
34437
+ "kind": "SCALAR",
34438
+ "name": "String",
34439
+ "ofType": null
34440
+ }
34441
+ },
34442
+ "isDeprecated": false,
34443
+ "deprecationReason": null
34444
+ },
34445
+ {
34446
+ "name": "matchLabels",
34447
+ "description": null,
34448
+ "args": [],
34449
+ "type": {
34450
+ "kind": "NON_NULL",
34451
+ "name": null,
34452
+ "ofType": {
34453
+ "kind": "SCALAR",
34454
+ "name": "JSON",
34455
+ "ofType": null
34456
+ }
34457
+ },
34458
+ "isDeprecated": false,
34459
+ "deprecationReason": null
34460
+ },
34461
+ {
34462
+ "name": "labelTemplate",
34463
+ "description": null,
34464
+ "args": [],
34465
+ "type": {
34466
+ "kind": "OBJECT",
34467
+ "name": "DynatraceTokenProviderLabelTemplate_v1",
34468
+ "ofType": null
34469
+ },
34470
+ "isDeprecated": false,
34471
+ "deprecationReason": null
34472
+ }
34473
+ ],
34474
+ "inputFields": null,
34475
+ "interfaces": [],
34476
+ "enumValues": null,
34477
+ "possibleTypes": null
34478
+ },
34479
+ {
34480
+ "kind": "OBJECT",
34481
+ "name": "DynatraceTokenProviderLabelTemplate_v1",
34482
+ "description": null,
34483
+ "fields": [
34484
+ {
34485
+ "name": "path",
34486
+ "description": null,
34487
+ "args": [],
34488
+ "type": {
34489
+ "kind": "OBJECT",
34490
+ "name": "Resource_v1",
34491
+ "ofType": null
34492
+ },
34493
+ "isDeprecated": false,
34494
+ "deprecationReason": null
34495
+ },
34496
+ {
34497
+ "name": "type",
34498
+ "description": null,
34499
+ "args": [],
34500
+ "type": {
34501
+ "kind": "SCALAR",
34502
+ "name": "String",
34503
+ "ofType": null
34504
+ },
34505
+ "isDeprecated": false,
34506
+ "deprecationReason": null
34507
+ },
34508
+ {
34509
+ "name": "variables",
34510
+ "description": null,
34511
+ "args": [],
34512
+ "type": {
34513
+ "kind": "SCALAR",
34514
+ "name": "JSON",
34515
+ "ofType": null
34516
+ },
34517
+ "isDeprecated": false,
34518
+ "deprecationReason": null
34519
+ }
34520
+ ],
34521
+ "inputFields": null,
34522
+ "interfaces": [],
34523
+ "enumValues": null,
34524
+ "possibleTypes": null
34525
+ },
34207
34526
  {
34208
34527
  "kind": "OBJECT",
34209
34528
  "name": "__Schema",
@@ -38529,6 +38848,81 @@
38529
38848
  "enumValues": null,
38530
38849
  "possibleTypes": null
38531
38850
  },
38851
+ {
38852
+ "kind": "OBJECT",
38853
+ "name": "DynatraceTokenProviderCluster_v1",
38854
+ "description": null,
38855
+ "fields": [
38856
+ {
38857
+ "name": "name",
38858
+ "description": null,
38859
+ "args": [],
38860
+ "type": {
38861
+ "kind": "NON_NULL",
38862
+ "name": null,
38863
+ "ofType": {
38864
+ "kind": "SCALAR",
38865
+ "name": "String",
38866
+ "ofType": null
38867
+ }
38868
+ },
38869
+ "isDeprecated": false,
38870
+ "deprecationReason": null
38871
+ },
38872
+ {
38873
+ "name": "serverUrl",
38874
+ "description": null,
38875
+ "args": [],
38876
+ "type": {
38877
+ "kind": "NON_NULL",
38878
+ "name": null,
38879
+ "ofType": {
38880
+ "kind": "SCALAR",
38881
+ "name": "String",
38882
+ "ofType": null
38883
+ }
38884
+ },
38885
+ "isDeprecated": false,
38886
+ "deprecationReason": null
38887
+ },
38888
+ {
38889
+ "name": "serverId",
38890
+ "description": null,
38891
+ "args": [],
38892
+ "type": {
38893
+ "kind": "NON_NULL",
38894
+ "name": null,
38895
+ "ofType": {
38896
+ "kind": "SCALAR",
38897
+ "name": "String",
38898
+ "ofType": null
38899
+ }
38900
+ },
38901
+ "isDeprecated": false,
38902
+ "deprecationReason": null
38903
+ },
38904
+ {
38905
+ "name": "labels",
38906
+ "description": null,
38907
+ "args": [],
38908
+ "type": {
38909
+ "kind": "NON_NULL",
38910
+ "name": null,
38911
+ "ofType": {
38912
+ "kind": "SCALAR",
38913
+ "name": "JSON",
38914
+ "ofType": null
38915
+ }
38916
+ },
38917
+ "isDeprecated": false,
38918
+ "deprecationReason": null
38919
+ }
38920
+ ],
38921
+ "inputFields": null,
38922
+ "interfaces": [],
38923
+ "enumValues": null,
38924
+ "possibleTypes": null
38925
+ },
38532
38926
  {
38533
38927
  "kind": "OBJECT",
38534
38928
  "name": "NamespaceCNAsset_v1",
@@ -26,6 +26,7 @@ from reconcile.gql_definitions.common.saas_files import (
26
26
  SaasResourceTemplateTargetPromotionV1,
27
27
  SaasResourceTemplateTargetUpstreamV1,
28
28
  SaasResourceTemplateTargetV2,
29
+ SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1,
29
30
  SaasResourceTemplateTargetV2_SaasSecretParametersV1,
30
31
  SaasResourceTemplateV2_SaasSecretParametersV1,
31
32
  SaasSecretParametersV1,
@@ -65,6 +66,9 @@ class SaasResourceTemplateTarget(ConfiguredBaseModel):
65
66
  ) = Field(..., alias="secretParameters")
66
67
  upstream: SaasResourceTemplateTargetUpstreamV1 | None = Field(..., alias="upstream")
67
68
  image: SaasResourceTemplateTargetImageV1 | None = Field(..., alias="image")
69
+ images: (
70
+ list[SaasResourceTemplateTargetV2_SaasResourceTemplateTargetImageV1] | None
71
+ ) = Field(..., alias="images")
68
72
  disable: bool | None = Field(..., alias="disable")
69
73
  delete: bool | None = Field(..., alias="delete")
70
74
 
@@ -326,6 +326,9 @@ class SaasResourceTemplateTarget(HasParameters, HasSecretParameters, Protocol):
326
326
  @property
327
327
  def image(self) -> SaasResourceTemplateTargetImage | None: ...
328
328
 
329
+ @property
330
+ def images(self) -> Sequence[SaasResourceTemplateTargetImage] | None: ...
331
+
329
332
  def uid(
330
333
  self, parent_saas_file_name: str, parent_resource_template_name: str
331
334
  ) -> str: ...
@@ -113,14 +113,15 @@ class TriggerSpecUpstreamJob(TriggerSpecBase):
113
113
 
114
114
  @dataclass
115
115
  class TriggerSpecContainerImage(TriggerSpecBase):
116
- image: str
116
+ images: Sequence[str]
117
117
  reason: str | None = None
118
118
 
119
119
  @property
120
120
  def state_key(self) -> str:
121
+ image_key = "/".join(sorted(self.images))
121
122
  key = (
122
123
  f"{self.saas_file_name}/{self.resource_template_name}/{self.cluster_name}/"
123
- f"{self.namespace_name}/{self.env_name}/{self.image}"
124
+ f"{self.namespace_name}/{self.env_name}/{image_key}"
124
125
  )
125
126
  return key
126
127
 
@@ -102,6 +102,10 @@ Resource = dict[str, Any]
102
102
  Resources = list[Resource]
103
103
 
104
104
 
105
+ class TriggerSpecContainerImageError(Exception):
106
+ pass
107
+
108
+
105
109
  class SaasHerder: # pylint: disable=too-many-public-methods
106
110
  """Wrapper around SaaS deployment actions."""
107
111
 
@@ -1616,25 +1620,36 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1616
1620
  for rt in saas_file.resource_templates:
1617
1621
  for target in rt.targets:
1618
1622
  try:
1619
- if not target.image:
1623
+ if not (target.image or target.images):
1620
1624
  continue
1625
+ if target.image and target.images:
1626
+ raise TriggerSpecContainerImageError(
1627
+ '"image" and "images" are mutually exclusive. Do not set both in the same saas target.'
1628
+ )
1621
1629
  commit_sha = self._get_commit_sha(
1622
1630
  url=rt.url,
1623
1631
  ref=target.ref,
1624
1632
  github=github,
1625
1633
  )
1626
- desired_image_tag = commit_sha[: rt.hash_length or self.hash_length]
1627
- # don't trigger if image doesn't exist
1628
- image_registry = f"{target.image.org.instance.url}/{target.image.org.name}/{target.image.name}"
1629
- image_uri = f"{image_registry}:{desired_image_tag}"
1630
1634
  image_auth = self._initiate_image_auth(saas_file)
1635
+ desired_image_tag = commit_sha[: rt.hash_length or self.hash_length]
1636
+
1637
+ all_images = [target.image] if target.image else target.images or []
1638
+ image_registries = [
1639
+ f"{image.org.instance.url}/{image.org.name}/{image.name}"
1640
+ for image in all_images
1641
+ ]
1631
1642
  error_prefix = f"[{saas_file.name}/{rt.name}] {target.ref}:"
1632
- image = self._get_image(
1633
- image_uri, saas_file.image_patterns, image_auth, error_prefix
1634
- )
1635
- if not image:
1643
+ if not all(
1644
+ self._get_image(
1645
+ image=f"{image}:{desired_image_tag}",
1646
+ image_patterns=saas_file.image_patterns,
1647
+ image_auth=image_auth,
1648
+ error_prefix=error_prefix,
1649
+ )
1650
+ for image in image_registries
1651
+ ):
1636
1652
  continue
1637
-
1638
1653
  trigger_spec = TriggerSpecContainerImage(
1639
1654
  saas_file_name=saas_file.name,
1640
1655
  env_name=target.namespace.environment.name,
@@ -1643,12 +1658,16 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1643
1658
  resource_template_name=rt.name,
1644
1659
  cluster_name=target.namespace.cluster.name,
1645
1660
  namespace_name=target.namespace.name,
1646
- image=image_registry,
1661
+ images=image_registries,
1647
1662
  state_content=desired_image_tag,
1648
1663
  )
1649
1664
  if self.include_trigger_trace:
1665
+ image_uris = ", ".join(
1666
+ f"{image}:{desired_image_tag}"
1667
+ for image in sorted(image_registries)
1668
+ )
1650
1669
  trigger_spec.reason = (
1651
- f"{rt.url}/commit/{commit_sha} build {image_uri}"
1670
+ f"{rt.url}/commit/{commit_sha} build {image_uris}"
1652
1671
  )
1653
1672
  if not self.state:
1654
1673
  raise Exception("state is not initialized")
@@ -77,8 +77,6 @@ from terrascript.resource import (
77
77
  aws_ec2_transit_gateway_vpc_attachment,
78
78
  aws_ec2_transit_gateway_vpc_attachment_accepter,
79
79
  aws_ecr_repository,
80
- aws_elasticache_parameter_group,
81
- aws_elasticache_replication_group,
82
80
  aws_elasticsearch_domain,
83
81
  aws_iam_access_key,
84
82
  aws_iam_group,
@@ -106,8 +104,6 @@ from terrascript.resource import (
106
104
  aws_lb_listener_rule,
107
105
  aws_lb_target_group,
108
106
  aws_lb_target_group_attachment,
109
- aws_msk_cluster,
110
- aws_msk_configuration,
111
107
  aws_ram_principal_association,
112
108
  aws_ram_resource_association,
113
109
  aws_ram_resource_share,
@@ -1645,8 +1641,6 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
1645
1641
  self.populate_tf_resource_rds(spec)
1646
1642
  elif provider == "s3":
1647
1643
  self.populate_tf_resource_s3(spec)
1648
- elif provider == "elasticache":
1649
- self.populate_tf_resource_elasticache(spec)
1650
1644
  elif provider == "aws-iam-service-account":
1651
1645
  self.populate_tf_resource_service_account(spec, ocm_map=ocm_map)
1652
1646
  elif provider == "secrets-manager-service-account":
@@ -1689,8 +1683,6 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
1689
1683
  self.populate_tf_resource_rosa_authenticator(spec)
1690
1684
  elif provider == "rosa-authenticator-vpce":
1691
1685
  self.populate_tf_resource_rosa_authenticator_vpce(spec)
1692
- elif provider == "msk":
1693
- self.populate_tf_resource_msk(spec)
1694
1686
  else:
1695
1687
  raise UnknownProviderError(provider)
1696
1688
 
@@ -2491,94 +2483,6 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
2491
2483
 
2492
2484
  return bucket_tf_resource
2493
2485
 
2494
- def populate_tf_resource_elasticache(self, spec):
2495
- account = spec.provisioner_name
2496
- identifier = spec.identifier
2497
- values = self.init_values(spec)
2498
- output_prefix = spec.output_prefix
2499
- values.setdefault("replication_group_id", values["identifier"])
2500
- values.pop("identifier", None)
2501
-
2502
- tf_resources = []
2503
- self.init_common_outputs(tf_resources, spec)
2504
-
2505
- default_region = self.default_regions.get(account)
2506
- desired_region = values.pop("region", default_region)
2507
-
2508
- provider = ""
2509
- if desired_region is not None and self._multiregion_account(account):
2510
- provider = "aws." + desired_region
2511
- values["provider"] = provider
2512
-
2513
- if not values.get("apply_immediately"):
2514
- values["apply_immediately"] = False
2515
-
2516
- parameter_group = values.get("parameter_group")
2517
- # Assume that cluster enabled is false if parameter group unset
2518
- pg_cluster_enabled = False
2519
-
2520
- if parameter_group:
2521
- pg_values = self.get_values(parameter_group)
2522
- pg_name = pg_values["name"]
2523
- pg_identifier = pg_name
2524
-
2525
- # If the desired region is not the same as the default region
2526
- # we append the region to the identifier to make it unique
2527
- # in the terraform config
2528
- if desired_region is not None and desired_region != default_region:
2529
- pg_identifier = f"{pg_name}-{desired_region}"
2530
-
2531
- pg_values["parameter"] = pg_values.pop("parameters")
2532
- for param in pg_values["parameter"]:
2533
- if param["name"] == "cluster-enabled" and param["value"] == "yes":
2534
- pg_cluster_enabled = True
2535
-
2536
- if self._multiregion_account(account) and len(provider) > 0:
2537
- pg_values["provider"] = provider
2538
- pg_tf_resource = aws_elasticache_parameter_group(pg_identifier, **pg_values)
2539
- tf_resources.append(pg_tf_resource)
2540
- values["depends_on"] = [
2541
- f"aws_elasticache_parameter_group.{pg_identifier}",
2542
- ]
2543
- values["parameter_group_name"] = pg_name
2544
- values.pop("parameter_group", None)
2545
-
2546
- auth_token = spec.get_secret_field("db.auth_token")
2547
- if not auth_token:
2548
- auth_token = self.generate_random_password()
2549
-
2550
- if values.get("transit_encryption_enabled", False):
2551
- values["auth_token"] = auth_token
2552
-
2553
- # elasticache replication group
2554
- # Ref: https://www.terraform.io/docs/providers/aws/r/
2555
- # elasticache_replication_group.html
2556
- tf_resource = aws_elasticache_replication_group(identifier, **values)
2557
- tf_resources.append(tf_resource)
2558
- # elasticache outputs
2559
- # we want the outputs to be formed into an OpenShift Secret
2560
- # with the following fields
2561
- # db.endpoint
2562
- output_name = output_prefix + "__db_endpoint"
2563
- # https://docs.aws.amazon.com/AmazonElastiCache/
2564
- # latest/red-ug/Endpoints.html
2565
- if pg_cluster_enabled:
2566
- output_value = "${" + tf_resource.configuration_endpoint_address + "}"
2567
- else:
2568
- output_value = "${" + tf_resource.primary_endpoint_address + "}"
2569
- tf_resources.append(Output(output_name, value=output_value))
2570
- # db.port
2571
- output_name = output_prefix + "__db_port"
2572
- output_value = "${" + str(tf_resource.port) + "}"
2573
- tf_resources.append(Output(output_name, value=output_value))
2574
- # db.auth_token
2575
- if values.get("transit_encryption_enabled", False):
2576
- output_name = output_prefix + "__db_auth_token"
2577
- output_value = values["auth_token"]
2578
- tf_resources.append(Output(output_name, value=output_value, sensitive=True))
2579
-
2580
- self.add_resources(account, tf_resources)
2581
-
2582
2486
  def populate_tf_resource_service_account(self, spec, ocm_map=None):
2583
2487
  account = spec.provisioner_name
2584
2488
  identifier = spec.identifier
@@ -4287,24 +4191,6 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
4287
4191
  values["db_name"] = db_name
4288
4192
  if values.get("replica_source"):
4289
4193
  values.pop("db_name", None)
4290
- elif spec.provider == "elasticache":
4291
- if description := values.pop("replication_group_description", None):
4292
- values["description"] = description
4293
- if num_cache_clusters := values.pop("number_cache_clusters", None):
4294
- values["num_cache_clusters"] = num_cache_clusters
4295
- if cluster_mode := values.pop("cluster_mode", {}):
4296
- for k, v in cluster_mode.items():
4297
- values[k] = v
4298
- values.pop("availability_zones", None)
4299
- elif spec.provider == "msk":
4300
- if ebs_volume_size := values.get("broker_node_group_info", {}).pop(
4301
- "ebs_volume_size", None
4302
- ):
4303
- values["broker_node_group_info"].setdefault(
4304
- "storage_info", {}
4305
- ).setdefault("ebs_storage_info", {})[
4306
- "volume_size"
4307
- ] = ebs_volume_size
4308
4194
 
4309
4195
  return values
4310
4196
 
@@ -6656,205 +6542,6 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
6656
6542
 
6657
6543
  self.add_resources(account, tf_resources)
6658
6544
 
6659
- def populate_tf_resource_msk(self, spec):
6660
- account = spec.provisioner_name
6661
- values = self.init_values(spec)
6662
- output_prefix = spec.output_prefix
6663
- tf_resources = []
6664
- resource_id = spec.identifier
6665
-
6666
- del values["identifier"]
6667
- values.setdefault("cluster_name", spec.identifier)
6668
-
6669
- # common
6670
- self.init_common_outputs(tf_resources, spec)
6671
-
6672
- # validations
6673
- if (
6674
- values["number_of_broker_nodes"]
6675
- % len(values["broker_node_group_info"]["client_subnets"])
6676
- != 0
6677
- ):
6678
- raise ValueError(
6679
- "number_of_broker_nodes must be a multiple of the number of specified client subnets."
6680
- )
6681
-
6682
- scram_enabled = (
6683
- values.get("client_authentication", {}).get("sasl", {}).get("scram", False)
6684
- )
6685
- scram_users = {}
6686
- if scram_enabled:
6687
- if not spec.resource.get("users", []):
6688
- raise ValueError(
6689
- "users attribute must be given when client_authentication.sasl.scram is enabled."
6690
- )
6691
- scram_users = {
6692
- user["name"]: self.secret_reader.read_all(user["secret"])
6693
- for user in spec.resource["users"]
6694
- }
6695
- # validate user objects
6696
- for user, secret in scram_users.items():
6697
- if secret.keys() != {"password", "username"}:
6698
- raise ValueError(
6699
- f"MSK user '{user}' secret must contain only 'username' and 'password' keys!"
6700
- )
6701
-
6702
- # resource - msk config
6703
- # unique msk config resource name enables "create_before_destroy" lifecycle
6704
- # which is required when changing version which requires a resource replacement
6705
- msk_version_str = values["kafka_version"].replace(".", "-")
6706
- msk_config_name = f"{resource_id}-{msk_version_str}"
6707
- msk_config = aws_msk_configuration(
6708
- msk_config_name,
6709
- name=msk_config_name,
6710
- kafka_versions=[values["kafka_version"]],
6711
- server_properties=values["server_properties"],
6712
- # lifecycle create_before_destroy is required to ensure that the config is created
6713
- # before it is assigned to the cluster
6714
- lifecycle={
6715
- "create_before_destroy": True,
6716
- },
6717
- )
6718
- tf_resources.append(msk_config)
6719
- values.pop("server_properties", None)
6720
-
6721
- # resource - cluster
6722
- values["configuration_info"] = {
6723
- "arn": "${" + msk_config.arn + "}",
6724
- "revision": "${" + msk_config.latest_revision + "}",
6725
- }
6726
- msk_cluster = aws_msk_cluster(resource_id, **values)
6727
- tf_resources.append(msk_cluster)
6728
-
6729
- # resource - cloudwatch
6730
- if (
6731
- values.get("logging_info", {})
6732
- .get("broker_logs", {})
6733
- .get("cloudwatch_logs", {})
6734
- .get("enabled", False)
6735
- ):
6736
- log_group_values = {
6737
- "name": f"{resource_id}-msk-broker-logs",
6738
- "tags": values["tags"],
6739
- "retention_in_days": values["logging_info"]["broker_logs"][
6740
- "cloudwatch_logs"
6741
- ]["retention_in_days"],
6742
- }
6743
- log_group_tf_resource = aws_cloudwatch_log_group(
6744
- resource_id, **log_group_values
6745
- )
6746
- tf_resources.append(log_group_tf_resource)
6747
- del values["logging_info"]["broker_logs"]["cloudwatch_logs"][
6748
- "retention_in_days"
6749
- ]
6750
- values["logging_info"]["broker_logs"]["cloudwatch_logs"]["log_group"] = (
6751
- log_group_tf_resource.name
6752
- )
6753
-
6754
- # resource - secret manager for SCRAM client credentials
6755
- if scram_enabled and scram_users:
6756
- scram_secrets: list[
6757
- tuple[aws_secretsmanager_secret, aws_secretsmanager_secret_version]
6758
- ] = []
6759
-
6760
- # kms
6761
- kms_values = {
6762
- "description": "KMS key for MSK SCRAM credentials",
6763
- "tags": values["tags"],
6764
- }
6765
- kms_key = aws_kms_key(resource_id, **kms_values)
6766
- tf_resources.append(kms_key)
6767
-
6768
- kms_key_alias = aws_kms_alias(
6769
- resource_id,
6770
- name=f"alias/{resource_id}-msk-scram",
6771
- target_key_id="${" + kms_key.arn + "}",
6772
- )
6773
- tf_resources.append(kms_key_alias)
6774
-
6775
- for user, secret in scram_users.items():
6776
- secret_identifier = f"AmazonMSK_{resource_id}-{user}"
6777
-
6778
- secret_values = {
6779
- "name": secret_identifier,
6780
- "tags": values["tags"],
6781
- "kms_key_id": "${" + kms_key.arn + "}",
6782
- }
6783
- secret_resource = aws_secretsmanager_secret(
6784
- secret_identifier, **secret_values
6785
- )
6786
- tf_resources.append(secret_resource)
6787
-
6788
- version_values = {
6789
- "secret_id": "${" + secret_resource.arn + "}",
6790
- "secret_string": json.dumps(secret, sort_keys=True),
6791
- }
6792
- version_resource = aws_secretsmanager_secret_version(
6793
- secret_identifier, **version_values
6794
- )
6795
- tf_resources.append(version_resource)
6796
-
6797
- secret_policy_values = {
6798
- "secret_arn": "${" + secret_resource.arn + "}",
6799
- "policy": json.dumps({
6800
- "Version": "2012-10-17",
6801
- "Statement": [
6802
- {
6803
- "Sid": "AWSKafkaResourcePolicy",
6804
- "Effect": "Allow",
6805
- "Principal": {"Service": "kafka.amazonaws.com"},
6806
- "Action": "secretsmanager:getSecretValue",
6807
- "Resource": "${" + secret_resource.arn + "}",
6808
- }
6809
- ],
6810
- }),
6811
- }
6812
- secret_policy = aws_secretsmanager_secret_policy(
6813
- secret_identifier, **secret_policy_values
6814
- )
6815
- tf_resources.append(secret_policy)
6816
- scram_secrets.append((secret_resource, version_resource))
6817
-
6818
- # create ONE scram secret association for each secret created above
6819
- scram_secret_association_values = {
6820
- "cluster_arn": "${" + msk_cluster.arn + "}",
6821
- "secret_arn_list": ["${" + s.arn + "}" for s, _ in scram_secrets],
6822
- "depends_on": self.get_dependencies([v for _, v in scram_secrets]),
6823
- }
6824
- scram_secret_association = aws_msk_scram_secret_association(
6825
- resource_id, **scram_secret_association_values
6826
- )
6827
- tf_resources.append(scram_secret_association)
6828
-
6829
- # outputs
6830
- tf_resources += [
6831
- Output(
6832
- output_prefix + "__zookeeper_connect_string",
6833
- value="${" + msk_cluster.zookeeper_connect_string + "}",
6834
- ),
6835
- Output(
6836
- output_prefix + "__zookeeper_connect_string_tls",
6837
- value="${" + msk_cluster.zookeeper_connect_string_tls + "}",
6838
- ),
6839
- Output(
6840
- output_prefix + "__bootstrap_brokers",
6841
- value="${" + msk_cluster.bootstrap_brokers + "}",
6842
- ),
6843
- Output(
6844
- output_prefix + "__bootstrap_brokers_tls",
6845
- value="${" + msk_cluster.bootstrap_brokers_tls + "}",
6846
- ),
6847
- Output(
6848
- output_prefix + "__bootstrap_brokers_sasl_iam",
6849
- value="${" + msk_cluster.bootstrap_brokers_sasl_iam + "}",
6850
- ),
6851
- Output(
6852
- output_prefix + "__bootstrap_brokers_sasl_scram",
6853
- value="${" + msk_cluster.bootstrap_brokers_sasl_scram + "}",
6854
- ),
6855
- ]
6856
- self.add_resources(account, tf_resources)
6857
-
6858
6545
  def populate_saml_idp(self, account_name: str, name: str, metadata: str) -> None:
6859
6546
  saml_idp = aws_iam_saml_provider(
6860
6547
  f"{account_name}-{name}", name=name, saml_metadata_document=metadata