qontract-reconcile 0.10.1rc764__py3-none-any.whl → 0.10.1rc766__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.
Files changed (34) hide show
  1. {qontract_reconcile-0.10.1rc764.dist-info → qontract_reconcile-0.10.1rc766.dist-info}/METADATA +1 -1
  2. {qontract_reconcile-0.10.1rc764.dist-info → qontract_reconcile-0.10.1rc766.dist-info}/RECORD +19 -34
  3. reconcile/gql_definitions/ldap_groups/roles.py +12 -2
  4. reconcile/ldap_groups/integration.py +36 -23
  5. reconcile/saas_auto_promotions_manager/meta.py +1 -1
  6. reconcile/saas_auto_promotions_manager/subscriber.py +52 -2
  7. reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +4 -0
  8. reconcile/test/saas_auto_promotions_manager/conftest.py +63 -0
  9. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -37
  10. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py +20 -14
  11. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -43
  12. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +4 -11
  13. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +12 -19
  14. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +6 -12
  15. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_json_path_selector.py +8 -15
  16. reconcile/utils/internal_groups/models.py +1 -1
  17. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/data_keys.py +0 -4
  18. reconcile/test/saas_auto_promotions_manager/subscriber/__init__.py +0 -0
  19. reconcile/test/saas_auto_promotions_manager/subscriber/conftest.py +0 -89
  20. reconcile/test/saas_auto_promotions_manager/subscriber/data_keys.py +0 -11
  21. reconcile/test/saas_auto_promotions_manager/subscriber/test_content_hash.py +0 -130
  22. reconcile/test/saas_auto_promotions_manager/subscriber/test_diff.py +0 -161
  23. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_config_hash.py +0 -218
  24. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_moving_ref.py +0 -216
  25. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_publishers_moving_ref.py +0 -129
  26. reconcile/test/saas_auto_promotions_manager/subscriber/test_single_channel_with_single_publisher.py +0 -330
  27. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/__init__.py +0 -0
  28. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_multiple_publishers_for_single_channel.py +0 -68
  29. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_use_target_config_hash.py +0 -62
  30. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_with_auto_promote.py +0 -73
  31. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_without_auto_promote.py +0 -64
  32. {qontract_reconcile-0.10.1rc764.dist-info → qontract_reconcile-0.10.1rc766.dist-info}/WHEEL +0 -0
  33. {qontract_reconcile-0.10.1rc764.dist-info → qontract_reconcile-0.10.1rc766.dist-info}/entry_points.txt +0 -0
  34. {qontract_reconcile-0.10.1rc764.dist-info → qontract_reconcile-0.10.1rc766.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc764
3
+ Version: 0.10.1rc766
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
@@ -308,7 +308,7 @@ reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions
308
308
  reconcile/gql_definitions/jumphosts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
309
309
  reconcile/gql_definitions/jumphosts/jumphosts.py,sha256=gN595lx7K1XsB2AfxDQ911TBVBbCoxibVeujnsGue_Q,2371
310
310
  reconcile/gql_definitions/ldap_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
- reconcile/gql_definitions/ldap_groups/roles.py,sha256=RVTDgMExKb2BGq4dVeBYm5p7HMJlbjme-YkUWh8ikkA,2612
311
+ reconcile/gql_definitions/ldap_groups/roles.py,sha256=goGDnkBBFy0mdLsXqL9qlSLPCFd9rwiD1rrsIH-6nZQ,2888
312
312
  reconcile/gql_definitions/ldap_groups/settings.py,sha256=KR6eKqXQWVYZAUEdatL1RCARaTOWl9X-QmxEMVjVNDE,2227
313
313
  reconcile/gql_definitions/membershipsources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
314
314
  reconcile/gql_definitions/membershipsources/roles.py,sha256=d3nv3GLsj_eKgwB1glsiK6smpC4i16WO3dU5rIdRg94,3678
@@ -377,7 +377,7 @@ reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_c
377
377
  reconcile/jenkins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
378
378
  reconcile/jenkins/types.py,sha256=0UlyJxv3KY1WXHkfI_ghUI6FAwRJTL4EwvLg-62tNcg,3001
379
379
  reconcile/ldap_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
380
- reconcile/ldap_groups/integration.py,sha256=iVfR7bRz8up_bf5Q4aVZHuVoUT6U_aHHkcgY4S9RwqA,10113
380
+ reconcile/ldap_groups/integration.py,sha256=Jj4jWp1aypkoweVNQj7QzMtFKQIWeaunLtXZ8KyKOHE,10670
381
381
  reconcile/ocm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
382
382
  reconcile/ocm/types.py,sha256=ibJYvzfAZyyMFkcF1bP8u3rkXciYJRplt_7Z1pKHFh0,2484
383
383
  reconcile/ocm_internal_notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -407,10 +407,10 @@ reconcile/rhidp/sso_client/integration.py,sha256=kA8g7c38ZBSdrRtyfEqy_WgSreD1Pbw
407
407
  reconcile/rhidp/sso_client/metrics.py,sha256=Tq7tSOsqL3XdcPUdozxqzSPIodUeOV87UCTqpuuqqhw,1013
408
408
  reconcile/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
409
409
  reconcile/saas_auto_promotions_manager/integration.py,sha256=shWQ--FWfeh_1rHJUwOWDiZWnvzKxYJYuRUIGQv22RI,6759
410
- reconcile/saas_auto_promotions_manager/meta.py,sha256=2b44ik-qpACNtW72QlDa2YOQqxeN8FHZfLPDmKoH3Rg,161
410
+ reconcile/saas_auto_promotions_manager/meta.py,sha256=jzqK6qM2JDdCE5kzkcj1e1TBMAL9f6lM2Hse8yFb8W8,161
411
411
  reconcile/saas_auto_promotions_manager/publisher.py,sha256=psrthZGgCQDUO3rwQjKSBMlwcTgfij6sxdebGuxkNv4,2739
412
412
  reconcile/saas_auto_promotions_manager/s3_exporter.py,sha256=IKlVWZmiPnvl7sKeF6JgAlhXZe5CovKTxQc0SNkNSx4,2583
413
- reconcile/saas_auto_promotions_manager/subscriber.py,sha256=cLhPlkT71J2LIice3SLmH1WpsqzV46gd0peMxrnqyRw,7452
413
+ reconcile/saas_auto_promotions_manager/subscriber.py,sha256=NPhlagNF8om7ikrjRlYNSQ2Ra7wgW_3-OlEWapnjtW0,9405
414
414
  reconcile/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
415
415
  reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py,sha256=jgfgKv4UTYFxtDao_JwNEGEKmu4GpeMm5vbaat0289c,1225
416
416
  reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request.py,sha256=BeAJWLow7b4HQyZ9zz398sQkPeIz8chpMkCts2NU27c,1282
@@ -420,7 +420,7 @@ reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py,sha256
420
420
  reconcile/saas_auto_promotions_manager/merge_request_manager/reconciler.py,sha256=KZVAkFJR75Qu7-feV4mzg1S8ua-pkbuu1oC7PebSpDs,7801
421
421
  reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=iu0wMyyEvro5r5SBJVN3HGmVSIcxTyLN0Xxx3mhbYXE,7066
422
422
  reconcile/saas_auto_promotions_manager/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
423
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=ZNxwqp9kdUSoxb3kTdM4KrtPyd3V5O4jMfjrVT2IJfs,7605
423
+ reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=7LlTQCzYotWCbtYBaNQP81CFlLUOvsyGMBQE-Ha0cKY,7820
424
424
  reconcile/skupper_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
425
425
  reconcile/skupper_network/integration.py,sha256=178Q9RSYuZ9NmrCK4jRMLMekrewUaaRdclccI6zBsQ8,10786
426
426
  reconcile/skupper_network/models.py,sha256=DNTI7HZv-rqY42GIIxyRuvroHLvdH6rJerjIq9lj3RU,6663
@@ -534,38 +534,23 @@ reconcile/test/test_version_bump.py,sha256=q6-3Y1roriI6YWpFwaHOMN7emEP3yL33sh_0V
534
534
  reconcile/test/test_vpc_peerings_validator.py,sha256=dFSmjc_dMN2GqMbntCFpa7PUZmyYuQ9DKffh-T5wmxM,6639
535
535
  reconcile/test/test_wrong_region.py,sha256=7KzL7OaICQ9Z3DW27zt_ykMN7_87owAFC-2CYjvGoyA,2138
536
536
  reconcile/test/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
537
- reconcile/test/saas_auto_promotions_manager/conftest.py,sha256=tZNs35EuWulP53Cqt61RteOGY_uH4gfhtXfGQ8-awwM,3081
537
+ reconcile/test/saas_auto_promotions_manager/conftest.py,sha256=4BtuxVZ0Lsmdp6AhG8kbtowkwG7e-pSjIKv35Wm1hI0,5803
538
538
  reconcile/test/saas_auto_promotions_manager/test_integration_test.py,sha256=x7QgHDMKIoPRY8k2SRSWa7qY3Z5Vabsyh9xWCtMXtfY,1857
539
539
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
540
540
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
541
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py,sha256=7O3lbk1EmEtUofqGncfiwMYvDPXrkQNPB59zlQ_zXkM,4588
541
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py,sha256=HikuDsdDxJ6HW48WY50s_7fmeGr07kcRdBZxgHzwc-0,3514
542
542
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py,sha256=Z1IV51OUuzhd-3S8W-k7ixC-fkaglCokn0eakK0Z73s,606
543
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py,sha256=x5DDZog0SA-Z8noxwalZniGtkovaPvR0V9Pqa5QaFFY,2302
543
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py,sha256=OLtJ11SsznoT39_tudsozcksK0N3TVNv-JWhIrCVaQk,2356
544
544
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py,sha256=h8lnorFPZIxTtbaaXGLoiEsBbB4Qj-Mg9BKV62ZqEBQ,2389
545
545
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py,sha256=dcGHzxuafKSxmswSO1qF2WlKaqsmEvtERC6Lb8kDAN0,10019
546
546
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py,sha256=_bzfJzjFJgubu--7wyXIiusUrdbmLtFbHmkbat4SX_M,17828
547
547
  reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
548
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py,sha256=2rCSstewp4LPoEJHm5N7dGJexEtY8ndLHvoGZYjmpsc,1678
549
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/data_keys.py,sha256=beHYQ9kgDLeBZgC2FvxQA3tHx1PO-RAMN8_kVcSdikI,90
550
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py,sha256=mlsSuTKHTPEMDFmDJnpeZ5j9R0eZOK2KMj8kAm4nvRU,1116
551
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py,sha256=tS57UbNsJGb4kTnHNCPTfUEpLWwxprhtCeJOnvIt8A0,2527
552
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py,sha256=6g4s2c--W4l_PMTcCA_8aNM85YejwDZttQOz5Iowido,1908
553
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_json_path_selector.py,sha256=k_jA4x_9fRGGAT1T0aeAFiZwZ7zlDZpPPgqMDeuR7y8,2189
554
- reconcile/test/saas_auto_promotions_manager/subscriber/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
555
- reconcile/test/saas_auto_promotions_manager/subscriber/conftest.py,sha256=5hMe91UEp_GQm49OeTee4ALv_xq2KhWwF6NfzzQwpnc,3101
556
- reconcile/test/saas_auto_promotions_manager/subscriber/data_keys.py,sha256=2j4Ue-njmK53Xm4vJScT2MJJeKV7wk9xf_95pmNfLWE,402
557
- reconcile/test/saas_auto_promotions_manager/subscriber/test_content_hash.py,sha256=viw-p42vDOC2telE5lelssRBL7V35aNJ1qUg6D-QGWw,4546
558
- reconcile/test/saas_auto_promotions_manager/subscriber/test_diff.py,sha256=BkxCoWBlUahY5Vq36FX_t_UyIdzIc64CumzAd3imUAQ,4529
559
- reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_config_hash.py,sha256=0MeFuJnKUHdMXGe8v2Fzge1mhihTcKqr2OAMLEAyHP4,6439
560
- reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_moving_ref.py,sha256=rcF2tHltCsZiPQo23b-xjBuEqBHzVn4TMzHv_x0778o,6209
561
- reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_publishers_moving_ref.py,sha256=tGAjetYspWeevuuUCfbeU33noM-dP4lsb96UUAHkxWw,3588
562
- reconcile/test/saas_auto_promotions_manager/subscriber/test_single_channel_with_single_publisher.py,sha256=YDXCzrclRyKRW7qRBg9GB2HinJP_HPqzTcWMGD1rbFI,9452
548
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py,sha256=MjTLg7KwvdIYvxkCzgJG-gByD1fZxaq6c4SI6rWWUu8,552
549
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py,sha256=6LMsnbPx5svTF1nL6oQGLTp1NgjLG_tO56c0hbA2Di4,1059
550
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py,sha256=dc7vMOiVLl5yRUEfjF4eE7HfMZTbtT2dz1CMGJVLUZA,2526
551
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py,sha256=FY9pzmvE8uXvvt_P_G3M7_br8Zt1s428H23FlAj9nuY,1881
552
+ reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_json_path_selector.py,sha256=jCtG0hVCqJ-A4XBjwexDww5LQUXJFRc44O5rEMA7_7E,2160
563
553
  reconcile/test/saas_auto_promotions_manager/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
564
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
565
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_multiple_publishers_for_single_channel.py,sha256=jX8ade2615gRYiJ_Bui4F2kvv3rUyod5sdiMFhzcnsw,2168
566
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_use_target_config_hash.py,sha256=TThr7UeF8k7lNBeknknEcE4H9z-_K4jKdzNA_SqFKoY,1948
567
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_with_auto_promote.py,sha256=OSSdVEQ72npDRrbkx5JHhXus-0ku699wG7ecsco4axM,2545
568
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_without_auto_promote.py,sha256=6GoZ6ogpXBVYlRwag2wu9Z-1ES9LzyPxMqZkcX7oTA0,2040
569
554
  reconcile/typed_queries/__init__.py,sha256=rRk4CyslLsBr4vAh1pIPgt6s3P4R1M9NSEPLnyQgBpk,61
570
555
  reconcile/typed_queries/alerting_services_settings.py,sha256=sX6s8GY-BB0UHogMC1ICeREVab-IYrNm1c-hqMGEdYQ,864
571
556
  reconcile/typed_queries/app_interface_custom_messages.py,sha256=5HWr68_kb4bEL8pDCIH0ez6GOrdwdbGF6w88xV0_Ccs,718
@@ -707,7 +692,7 @@ reconcile/utils/glitchtip/client.py,sha256=KHUNjN8r2J67RxROIpjzs5cKsqbwjzsM_I1TA
707
692
  reconcile/utils/glitchtip/models.py,sha256=_oqZXNkyRTsAnx6tF4WUURSBj0cc9UNS4okOQYfAfB4,6435
708
693
  reconcile/utils/internal_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
709
694
  reconcile/utils/internal_groups/client.py,sha256=abREA8RwXKybXFjCK8CAcCr-iUp2r0tAbIEJ-c-PXws,4538
710
- reconcile/utils/internal_groups/models.py,sha256=jlkH_hyyyuwS0J1IpuS7W1AyQSKQ2QpHelXoH36edbE,2316
695
+ reconcile/utils/internal_groups/models.py,sha256=GSkF6fVcdbl774q51ZFUmNfSJPta03OcV67MgsuBR2E,2326
711
696
  reconcile/utils/jinja2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
712
697
  reconcile/utils/jinja2/extensions.py,sha256=zV_x8MhSHAynKhFnG3fULXrwsm5fUG_88IygZHSnN0o,1284
713
698
  reconcile/utils/jinja2/filters.py,sha256=_kJjdMsY3lGS5PUn4NnpXUQDNrL1IwiKsB-0MhTMGYM,4521
@@ -797,8 +782,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
797
782
  tools/test/test_qontract_cli.py,sha256=w2l4BHB09k1d-BGJ1jBUNCqDv7zkqYrMHojQXg-21kQ,4155
798
783
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
799
784
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
800
- qontract_reconcile-0.10.1rc764.dist-info/METADATA,sha256=Eov5cvApy_dlSvDlyNdI1Uk8pAO7tJZfv4cOMjUfeEA,2382
801
- qontract_reconcile-0.10.1rc764.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
802
- qontract_reconcile-0.10.1rc764.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
803
- qontract_reconcile-0.10.1rc764.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
804
- qontract_reconcile-0.10.1rc764.dist-info/RECORD,,
785
+ qontract_reconcile-0.10.1rc766.dist-info/METADATA,sha256=tFpqi2YNRp9SyjmZicHUP7W6onmCER5zHM7Y-fD6qa0,2382
786
+ qontract_reconcile-0.10.1rc766.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
787
+ qontract_reconcile-0.10.1rc766.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
788
+ qontract_reconcile-0.10.1rc766.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
789
+ qontract_reconcile-0.10.1rc766.dist-info/RECORD,,
@@ -33,7 +33,11 @@ fragment AWSAccountSSO on AWSAccount_v1 {
33
33
  query LdapGroupsRolesQuery {
34
34
  roles: roles_v1 {
35
35
  name
36
- ldapGroup
36
+ ldapGroup {
37
+ name
38
+ notes
39
+ membersAreOwners
40
+ }
37
41
  users {
38
42
  org_username
39
43
  }
@@ -58,6 +62,12 @@ class ConfiguredBaseModel(BaseModel):
58
62
  extra=Extra.forbid
59
63
 
60
64
 
65
+ class LdapGroupV1(ConfiguredBaseModel):
66
+ name: str = Field(..., alias="name")
67
+ notes: Optional[str] = Field(..., alias="notes")
68
+ members_are_owners: Optional[bool] = Field(..., alias="membersAreOwners")
69
+
70
+
61
71
  class UserV1(ConfiguredBaseModel):
62
72
  org_username: str = Field(..., alias="org_username")
63
73
 
@@ -72,7 +82,7 @@ class AWSGroupV1(ConfiguredBaseModel):
72
82
 
73
83
  class RoleV1(ConfiguredBaseModel):
74
84
  name: str = Field(..., alias="name")
75
- ldap_group: Optional[str] = Field(..., alias="ldapGroup")
85
+ ldap_group: Optional[LdapGroupV1] = Field(..., alias="ldapGroup")
76
86
  users: list[UserV1] = Field(..., alias="users")
77
87
  user_policies: Optional[list[AWSUserPolicyV1]] = Field(..., alias="user_policies")
78
88
  aws_groups: Optional[list[AWSGroupV1]] = Field(..., alias="aws_groups")
@@ -93,12 +93,12 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
93
93
  desired_groups_for_roles = self.get_desired_groups_for_roles(
94
94
  roles,
95
95
  contact_list=self.settings.contact_list,
96
- owners=[owner],
96
+ default_owners=[owner],
97
97
  )
98
98
  desired_groups_for_aws_roles = self.get_desired_groups_for_aws_roles(
99
99
  roles,
100
100
  contact_list=self.settings.contact_list,
101
- owners=[owner],
101
+ default_owners=[owner],
102
102
  )
103
103
  desired_groups = desired_groups_for_roles + desired_groups_for_aws_roles
104
104
 
@@ -147,7 +147,7 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
147
147
  data = roles_query(query_func, variables={})
148
148
  roles = [role for role in data.roles or []]
149
149
  if duplicates := find_duplicates(
150
- role.ldap_group for role in roles if role.ldap_group
150
+ role.ldap_group.name for role in roles if role.ldap_group
151
151
  ):
152
152
  for dup in duplicates:
153
153
  logging.error(f"{dup} is already in use by another role.")
@@ -155,30 +155,39 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
155
155
  return roles
156
156
 
157
157
  def get_desired_groups_for_roles(
158
- self, roles: Iterable[RoleV1], owners: Iterable[Entity], contact_list: str
158
+ self,
159
+ roles: Iterable[RoleV1],
160
+ default_owners: list[Entity],
161
+ contact_list: str,
159
162
  ) -> list[Group]:
160
163
  """Return the desired rover groups for the given roles."""
161
- return [
162
- Group(
163
- name=role.ldap_group,
164
- description="Persisted App-Interface role. Managed by qontract-reconcile",
165
- display_name=f"{role.ldap_group} (App-Interface))",
166
- members=[
167
- Entity(type=EntityType.USER, id=user.org_username)
168
- for user in role.users
169
- ],
170
- # only owners can modify the group (e.g. add/remove members)
171
- owners=owners,
172
- contact_list=contact_list,
164
+ groups = []
165
+ for role in roles:
166
+ if not role.ldap_group:
167
+ continue
168
+ members = [
169
+ Entity(type=EntityType.USER, id=user.org_username)
170
+ for user in role.users
171
+ ]
172
+ groups.append(
173
+ Group(
174
+ name=role.ldap_group.name,
175
+ description="Persisted App-Interface role. Managed by qontract-reconcile",
176
+ notes=role.ldap_group.notes,
177
+ display_name=f"{role.ldap_group.name} (App-Interface))",
178
+ members=members,
179
+ owners=default_owners
180
+ if not role.ldap_group.members_are_owners
181
+ else default_owners + members,
182
+ contact_list=contact_list,
183
+ )
173
184
  )
174
- for role in roles
175
- if role.ldap_group
176
- ]
185
+ return groups
177
186
 
178
187
  def get_desired_groups_for_aws_roles(
179
188
  self,
180
189
  roles: Iterable[RoleV1],
181
- owners: list[Entity],
190
+ default_owners: Iterable[Entity],
182
191
  contact_list: str,
183
192
  ) -> list[Group]:
184
193
  """Return the desired rover groups for all AWS roles."""
@@ -205,7 +214,7 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
205
214
  for user in role.users
206
215
  ],
207
216
  # only owners can modify the group (e.g. add/remove members)
208
- owners=owners,
217
+ owners=default_owners,
209
218
  contact_list=contact_list,
210
219
  )
211
220
  )
@@ -246,7 +255,9 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
246
255
  logging.info([
247
256
  "create_ldap_group",
248
257
  group_to_add.name,
249
- f"users={', '.join(u.id for u in group_to_add.members)}",
258
+ f"members={', '.join(u.id for u in group_to_add.members)}",
259
+ f"owners={', '.join(u.id for u in group_to_add.owners)}",
260
+ f"notes={group_to_add.notes}",
250
261
  ])
251
262
  if not dry_run:
252
263
  internal_groups_client.create_group(group_to_add)
@@ -266,7 +277,9 @@ class LdapGroupsIntegration(QontractReconcileIntegration[LdapGroupsIntegrationPa
266
277
  logging.info([
267
278
  "update_ldap_group",
268
279
  group_to_update.name,
269
- f"users={', '.join(u.id for u in group_to_update.members)}",
280
+ f"members={', '.join(u.id for u in group_to_update.members)}",
281
+ f"owners={', '.join(u.id for u in group_to_update.owners)}",
282
+ f"notes={group_to_update.notes}",
270
283
  ])
271
284
  if not dry_run:
272
285
  internal_groups_client.update_group(group_to_update)
@@ -1,4 +1,4 @@
1
1
  from reconcile.utils.semver_helper import make_semver
2
2
 
3
3
  QONTRACT_INTEGRATION = "saas-auto-promotions-manager"
4
- QONTRACT_INTEGRATION_VERSION = make_semver(2, 1, 4)
4
+ QONTRACT_INTEGRATION_VERSION = make_semver(2, 2, 0)
@@ -1,8 +1,8 @@
1
1
  import hashlib
2
2
  import logging
3
- from collections.abc import Iterable
3
+ from collections.abc import Iterable, Mapping
4
4
  from dataclasses import dataclass
5
- from typing import Optional
5
+ from typing import Any, Optional
6
6
 
7
7
  from reconcile.gql_definitions.fragments.saas_target_namespace import (
8
8
  SaasTargetNamespace,
@@ -42,6 +42,7 @@ class Subscriber:
42
42
  target_file_path: str,
43
43
  target_namespace: SaasTargetNamespace,
44
44
  use_target_config_hash: bool,
45
+ uid: str,
45
46
  ):
46
47
  self.saas_name = saas_name
47
48
  self.template_name = template_name
@@ -52,6 +53,7 @@ class Subscriber:
52
53
  self.desired_ref = ""
53
54
  self.desired_hashes: list[ConfigHash] = []
54
55
  self.target_namespace = target_namespace
56
+ self.uid = uid
55
57
  self._content_hash = ""
56
58
  self._use_target_config_hash = use_target_config_hash
57
59
 
@@ -73,6 +75,54 @@ class Subscriber:
73
75
  self._compute_desired_ref()
74
76
  self._compute_desired_config_hashes()
75
77
 
78
+ @staticmethod
79
+ def from_exported_dict(data: Mapping[str, Any]) -> "Subscriber":
80
+ subscriber = Subscriber(
81
+ saas_name=data["1"],
82
+ template_name=data["2"],
83
+ ref=data["3"],
84
+ target_file_path=data["4"],
85
+ use_target_config_hash=data["5"],
86
+ target_namespace=SaasTargetNamespace(**data["6"]),
87
+ uid=data["7"],
88
+ )
89
+ subscriber.desired_hashes = data["8"]
90
+ subscriber.desired_ref = data["9"]
91
+ return subscriber
92
+
93
+ def to_exportable_dict(self) -> dict[str, Any]:
94
+ """
95
+ We will later persist subscriber data as json in MRs. We keep key size small to use less space.
96
+ Note, the data will be encoded and encrypted in another component.
97
+ """
98
+ data: dict[str, Any] = {}
99
+ data["1"] = self.saas_name
100
+ data["2"] = self.template_name
101
+ data["3"] = self.ref
102
+ data["4"] = self.target_file_path
103
+ data["5"] = self._use_target_config_hash
104
+ data["6"] = self.target_namespace.dict(by_alias=True)
105
+ data["7"] = self.uid
106
+ data["8"] = self.desired_hashes
107
+ data["9"] = self.desired_ref
108
+ return data
109
+
110
+ def __eq__(self, other: object) -> bool:
111
+ if not isinstance(other, Subscriber):
112
+ # don't attempt to compare against unrelated types
113
+ return False
114
+ return (
115
+ self.saas_name == other.saas_name
116
+ and self.template_name == other.template_name
117
+ and self.ref == other.ref
118
+ and self.target_file_path == other.target_file_path
119
+ and self._use_target_config_hash == other._use_target_config_hash
120
+ and self.desired_ref == other.desired_ref
121
+ and self.desired_hashes == other.desired_hashes
122
+ and self.target_namespace == other.target_namespace
123
+ and self.uid == other.uid
124
+ )
125
+
76
126
  def _validate_deployment(
77
127
  self, publisher: Publisher, channel: Channel
78
128
  ) -> Optional[DeploymentInfo]:
@@ -92,6 +92,10 @@ class SaasFilesInventory:
92
92
  if not target.promotion.auto:
93
93
  continue
94
94
  subscriber = Subscriber(
95
+ uid=target.uid(
96
+ parent_saas_file_name=saas_file.name,
97
+ parent_resource_template_name=resource_template.name,
98
+ ),
95
99
  saas_name=saas_file.name,
96
100
  template_name=resource_template.name,
97
101
  target_file_path=file_path,
@@ -1,9 +1,11 @@
1
+ from collections import defaultdict
1
2
  from collections.abc import (
2
3
  Callable,
3
4
  Iterable,
4
5
  Mapping,
5
6
  MutableMapping,
6
7
  )
8
+ from typing import Any
7
9
  from unittest.mock import (
8
10
  MagicMock,
9
11
  create_autospec,
@@ -14,6 +16,12 @@ import pytest
14
16
  from reconcile.gql_definitions.fragments.saas_target_namespace import (
15
17
  SaasTargetNamespace,
16
18
  )
19
+ from reconcile.saas_auto_promotions_manager.publisher import DeploymentInfo, Publisher
20
+ from reconcile.saas_auto_promotions_manager.subscriber import (
21
+ Channel,
22
+ ConfigHash,
23
+ Subscriber,
24
+ )
17
25
  from reconcile.typed_queries.saas_files import SaasFile
18
26
  from reconcile.utils.gitlab_api import GitLabApi
19
27
  from reconcile.utils.promotion_state import (
@@ -100,3 +108,58 @@ def promotion_state_builder() -> Callable[..., PromotionState]:
100
108
  return promotion_state
101
109
 
102
110
  return builder
111
+
112
+
113
+ @pytest.fixture
114
+ def subscriber_builder(
115
+ saas_target_namespace_builder: Callable[..., SaasTargetNamespace],
116
+ ) -> Callable[[Mapping[str, Any]], Subscriber]:
117
+ def builder(data: Mapping[str, Any]) -> Subscriber:
118
+ channels: list[Channel] = []
119
+ for channel_name, channel_data in data.get("CHANNELS", {}).items():
120
+ channel = Channel(name=channel_name, publishers=[])
121
+ for publisher_name, publisher_data in channel_data.items():
122
+ publisher = Publisher(
123
+ ref="",
124
+ uid="",
125
+ repo_url="",
126
+ cluster_name="",
127
+ namespace_name="",
128
+ saas_name="",
129
+ saas_file_path="",
130
+ app_name="",
131
+ resource_template_name="",
132
+ target_name=None,
133
+ publish_job_logs=True,
134
+ has_subscriber=True,
135
+ auth_code=None,
136
+ )
137
+ publisher.commit_sha = publisher_data["REAL_WORLD_SHA"]
138
+ publisher.deployment_info_by_channel[channel_name] = DeploymentInfo(
139
+ success=publisher_data.get("SUCCESSFUL_DEPLOYMENT", True),
140
+ target_config_hash=publisher_data.get("CONFIG_HASH", ""),
141
+ saas_file=publisher_name,
142
+ )
143
+ channel.publishers.append(publisher)
144
+ channels.append(channel)
145
+ cur_config_hashes_by_channel: dict[str, list[ConfigHash]] = defaultdict(list)
146
+ for cur_config_hash in data.get("CUR_CONFIG_HASHES", []):
147
+ cur_config_hashes_by_channel[cur_config_hash.channel].append(
148
+ cur_config_hash
149
+ )
150
+ subscriber = Subscriber(
151
+ uid=data.get("SUB_UID", "default"),
152
+ target_namespace=saas_target_namespace_builder(data.get("NAMESPACE", {})),
153
+ ref=data.get("CUR_SUBSCRIBER_REF", ""),
154
+ saas_name="",
155
+ target_file_path=data.get("TARGET_FILE_PATH", ""),
156
+ template_name="",
157
+ use_target_config_hash=data.get("USE_TARGET_CONFIG_HASH", True),
158
+ )
159
+ subscriber.channels = channels
160
+ subscriber.config_hashes_by_channel_name = cur_config_hashes_by_channel
161
+ subscriber.desired_ref = data.get("DESIRED_REF", "")
162
+ subscriber.desired_hashes = data.get("DESIRED_TARGET_HASHES", [])
163
+ return subscriber
164
+
165
+ return builder
@@ -8,9 +8,6 @@ from unittest.mock import create_autospec
8
8
  import pytest
9
9
  from gitlab.v4.objects import ProjectMergeRequest
10
10
 
11
- from reconcile.gql_definitions.fragments.saas_target_namespace import (
12
- SaasTargetNamespace,
13
- )
14
11
  from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
15
12
  SAPM_LABEL,
16
13
  )
@@ -31,24 +28,17 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer impor
31
28
  VERSION_REF,
32
29
  Renderer,
33
30
  )
34
- from reconcile.saas_auto_promotions_manager.subscriber import (
35
- Channel,
36
- Subscriber,
37
- )
38
31
  from reconcile.utils.vcs import VCS, MRCheckStatus
39
32
 
40
33
  from .data_keys import (
41
- CHANNEL,
42
34
  DESCRIPTION,
43
35
  HAS_CONFLICTS,
44
36
  LABELS,
45
37
  OPEN_MERGE_REQUESTS,
46
38
  PIPELINE_RESULTS,
47
- REF,
48
39
  SUBSCRIBER_BATCHABLE,
49
40
  SUBSCRIBER_CHANNELS,
50
41
  SUBSCRIBER_CONTENT_HASH,
51
- SUBSCRIBER_TARGET_PATH,
52
42
  )
53
43
 
54
44
 
@@ -120,33 +110,6 @@ def reconciler_builder() -> Callable[[Diff], Reconciler]:
120
110
  return builder
121
111
 
122
112
 
123
- @pytest.fixture
124
- def subscriber_builder(
125
- saas_target_namespace_builder: Callable[..., SaasTargetNamespace],
126
- ) -> Callable[..., Subscriber]:
127
- def builder(data: Mapping) -> Subscriber:
128
- subscriber = Subscriber(
129
- saas_name="",
130
- template_name="",
131
- target_namespace=saas_target_namespace_builder({}),
132
- ref="",
133
- target_file_path=data.get(SUBSCRIBER_TARGET_PATH, ""),
134
- use_target_config_hash=True,
135
- )
136
- subscriber.desired_hashes = []
137
- subscriber.desired_ref = data.get(REF, "")
138
- for channel in data.get(CHANNEL, []):
139
- subscriber.channels.append(
140
- Channel(
141
- name=channel,
142
- publishers=[],
143
- )
144
- )
145
- return subscriber
146
-
147
- return builder
148
-
149
-
150
113
  @pytest.fixture
151
114
  def renderer() -> Renderer:
152
115
  return create_autospec(spec=Renderer)
@@ -5,10 +5,6 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.desired_state
5
5
  )
6
6
  from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
7
7
 
8
- from .data_keys import (
9
- CHANNEL,
10
- )
11
-
12
8
 
13
9
  def test_desired_state_empty() -> None:
14
10
  desired_state = DesiredState(subscribers=[])
@@ -29,10 +25,14 @@ def test_desired_state_single_subscriber(
29
25
  def test_desired_state_multiple_subscribers_same_channel_combo(
30
26
  subscriber_builder: Callable[..., Subscriber],
31
27
  ) -> None:
32
- subscriber_a = subscriber_builder({CHANNEL: ["channel-a", "channel-b"]})
33
- subscriber_a.desired_ref = "ref-a"
34
- subscriber_b = subscriber_builder({CHANNEL: ["channel-a", "channel-b"]})
35
- subscriber_b.desired_ref = "ref-b"
28
+ subscriber_a = subscriber_builder({
29
+ "CHANNELS": {"channel-a": {}, "channel-b": {}},
30
+ "DESIRED_REF": "ref-a",
31
+ })
32
+ subscriber_b = subscriber_builder({
33
+ "CHANNELS": {"channel-a": {}, "channel-b": {}},
34
+ "DESIRED_REF": "ref-b",
35
+ })
36
36
  desired_state = DesiredState(subscribers=[subscriber_a, subscriber_b])
37
37
  assert len(desired_state.promotions) == 1
38
38
  assert desired_state.promotions[0].content_hashes == {
@@ -43,12 +43,18 @@ def test_desired_state_multiple_subscribers_same_channel_combo(
43
43
  def test_desired_state_multiple_subscribers_different_channel_combo(
44
44
  subscriber_builder: Callable[..., Subscriber],
45
45
  ) -> None:
46
- subscriber_a = subscriber_builder({CHANNEL: ["channel-a", "channel-b"]})
47
- subscriber_a.desired_ref = "ref-a"
48
- subscriber_b = subscriber_builder({CHANNEL: ["channel-a", "channel-b"]})
49
- subscriber_b.desired_ref = "ref-b"
50
- subscriber_c = subscriber_builder({CHANNEL: ["channel-b", "channel-c"]})
51
- subscriber_c.desired_ref = "ref-c"
46
+ subscriber_a = subscriber_builder({
47
+ "CHANNELS": {"channel-a": {}, "channel-b": {}},
48
+ "DESIRED_REF": "ref-a",
49
+ })
50
+ subscriber_b = subscriber_builder({
51
+ "CHANNELS": {"channel-a": {}, "channel-b": {}},
52
+ "DESIRED_REF": "ref-b",
53
+ })
54
+ subscriber_c = subscriber_builder({
55
+ "CHANNELS": {"channel-b": {}, "channel-c": {}},
56
+ "DESIRED_REF": "ref-c",
57
+ })
52
58
  desired_state = DesiredState(subscribers=[subscriber_a, subscriber_b, subscriber_c])
53
59
  sorted_promotions = sorted(desired_state.promotions)
54
60
  assert len(desired_state.promotions) == 2
@@ -1,26 +1,10 @@
1
1
  import os
2
2
  from collections.abc import (
3
3
  Callable,
4
- Mapping,
5
4
  )
6
5
 
7
6
  import pytest
8
7
 
9
- from reconcile.gql_definitions.fragments.saas_target_namespace import (
10
- SaasTargetNamespace,
11
- )
12
- from reconcile.saas_auto_promotions_manager.subscriber import (
13
- Channel,
14
- Subscriber,
15
- )
16
-
17
- from .data_keys import (
18
- CHANNELS,
19
- CONFIG_HASHES,
20
- NAMESPACE,
21
- REF,
22
- )
23
-
24
8
 
25
9
  @pytest.fixture
26
10
  def file_contents() -> Callable[[str], tuple[str, str]]:
@@ -39,30 +23,3 @@ def file_contents() -> Callable[[str], tuple[str, str]]:
39
23
  return (a, b)
40
24
 
41
25
  return contents
42
-
43
-
44
- @pytest.fixture
45
- def subscriber_builder(
46
- saas_target_namespace_builder: Callable[..., SaasTargetNamespace],
47
- ) -> Callable[[Mapping], Subscriber]:
48
- def builder(data: Mapping) -> Subscriber:
49
- subscriber = Subscriber(
50
- target_namespace=saas_target_namespace_builder(data.get(NAMESPACE, {})),
51
- ref="",
52
- saas_name="",
53
- target_file_path="",
54
- template_name="",
55
- use_target_config_hash=True,
56
- )
57
- subscriber.desired_ref = data[REF]
58
- subscriber.desired_hashes = data[CONFIG_HASHES]
59
- for channel in data.get(CHANNELS, []):
60
- subscriber.channels.append(
61
- Channel(
62
- name=channel,
63
- publishers=[],
64
- )
65
- )
66
- return subscriber
67
-
68
- return builder