qontract-reconcile 0.10.2.dev180__py3-none-any.whl → 0.10.2.dev182__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.
- {qontract_reconcile-0.10.2.dev180.dist-info → qontract_reconcile-0.10.2.dev182.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev180.dist-info → qontract_reconcile-0.10.2.dev182.dist-info}/RECORD +17 -17
- reconcile/dashdotdb_dora.py +3 -3
- reconcile/github_repo_permissions_validator.py +2 -1
- reconcile/integrations_manager.py +2 -2
- reconcile/saas_auto_promotions_manager/integration.py +10 -2
- reconcile/saas_auto_promotions_manager/subscriber.py +28 -0
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +32 -7
- reconcile/service_dependencies.py +4 -1
- reconcile/typed_queries/saas_files.py +2 -0
- reconcile/utils/gitlab_api.py +28 -0
- reconcile/utils/jjb_client.py +2 -1
- reconcile/utils/saasherder/saasherder.py +15 -17
- reconcile/utils/terrascript_aws_client.py +3 -2
- reconcile/utils/vcs.py +4 -2
- {qontract_reconcile-0.10.2.dev180.dist-info → qontract_reconcile-0.10.2.dev182.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev180.dist-info → qontract_reconcile-0.10.2.dev182.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev180.dist-info → qontract_reconcile-0.10.2.dev182.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.2.
|
3
|
+
Version: 0.10.2.dev182
|
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
|
{qontract_reconcile-0.10.2.dev180.dist-info → qontract_reconcile-0.10.2.dev182.dist-info}/RECORD
RENAMED
@@ -15,7 +15,7 @@ reconcile/closedbox_endpoint_monitoring_base.py,sha256=al7m8EgnnYx90rY1REryW3byN
|
|
15
15
|
reconcile/cluster_deployment_mapper.py,sha256=5gumAaRCcFXsabUJ1dnuUy9WrP_FEEM5JnOnE8ch9sE,2326
|
16
16
|
reconcile/dashdotdb_base.py,sha256=83ZWIf5JJk3P_D69y2TmXRcQr6ELJGlv10OM0h7fJVs,4767
|
17
17
|
reconcile/dashdotdb_cso.py,sha256=QRK0YfIqO4rehs8btD3l_GXIO2ZIycTQEKEthBdB0xA,3639
|
18
|
-
reconcile/dashdotdb_dora.py,sha256=
|
18
|
+
reconcile/dashdotdb_dora.py,sha256=hMh0Eq6ze5llWGoDV3l4OGcWY5OeJdS6Xy4b1Y4C_MY,17855
|
19
19
|
reconcile/dashdotdb_dvo.py,sha256=lCkZ0iby6HrNQb-3kYb6xrt8wCjVUZYxKzz9SiStfHU,8946
|
20
20
|
reconcile/dashdotdb_slo.py,sha256=TvKdMOtUZcZP9QydcUJMKh0zURHgOMN_RTpQpCkD1Z8,3960
|
21
21
|
reconcile/database_access_manager.py,sha256=Z3aAmw2LsmMIIor-bOGzziVZdVNC82Gmw8oHBUAFf-8,25577
|
@@ -26,7 +26,7 @@ reconcile/gcp_image_mirror.py,sha256=1ThuUff_04ZdF6uxcLoDuHhoNA3OIw0V-z0-CwdPE2w
|
|
26
26
|
reconcile/github_org.py,sha256=Wc5cZamatuWsW2ZJT2ib5ps8l3iY3RXHwNUxVJerqz0,14173
|
27
27
|
reconcile/github_owners.py,sha256=viE1KJ-zaTxuZ5yItg2C263J0brn-Q-3hR_DkYDMbhY,3122
|
28
28
|
reconcile/github_repo_invites.py,sha256=U9UCzNVwrZ7MqODtFah8ogH0NNY-XjBin7G9gqHtCUY,2690
|
29
|
-
reconcile/github_repo_permissions_validator.py,sha256=
|
29
|
+
reconcile/github_repo_permissions_validator.py,sha256=ske7cHJ-41jnaywgRlDnR2z9E1yLDSJ0tivq6bhhZdc,1827
|
30
30
|
reconcile/github_users.py,sha256=QdX164LZrm8sqggMj-0beCzWofpS6OEBfzKNrWPrfj0,3934
|
31
31
|
reconcile/github_validator.py,sha256=-j17tn3csFVjPMSPL3te48iWVkPZCncRXdeKeLdGjjQ,931
|
32
32
|
reconcile/gitlab_fork_compliance.py,sha256=RbHckzLnE9zkOFHJANzoejEMMbMAivmqJVs3Suvp9lU,4591
|
@@ -37,7 +37,7 @@ reconcile/gitlab_mr_sqs_consumer.py,sha256=i_MDVfA3Uk_TJiNkfEJzhO6_rwR7z3I3dH9oE
|
|
37
37
|
reconcile/gitlab_owners.py,sha256=nIEsf3QWI3yIw_Bxy5oMaCmszTaNZDwQVaaZZxPgh4g,14447
|
38
38
|
reconcile/gitlab_permissions.py,sha256=kZEdWL0rewP7Odz8amRBPToKxkn0IQn81IoroHGdga4,8101
|
39
39
|
reconcile/gitlab_projects.py,sha256=K3tFf_aD1W4Ijp5q-9Qek3kwFGEWPcZ1kd7tzFJ4GyQ,1781
|
40
|
-
reconcile/integrations_manager.py,sha256=
|
40
|
+
reconcile/integrations_manager.py,sha256=2Hz-ecNxoOVCGursvjz7SONp-cMfzcLogklAAtnDln0,9479
|
41
41
|
reconcile/jenkins_base.py,sha256=0Gocu3fU2YTltaxBlbDQOUvP-7CP2OSQV1ZRwtWeVXw,875
|
42
42
|
reconcile/jenkins_job_builder.py,sha256=2aeOSS5pwKJgF4EzoHBWlOYNbzLj3qYzv6u55Qg6MAg,3466
|
43
43
|
reconcile/jenkins_job_builds_cleaner.py,sha256=0iiX0iJiIIter0g9l0l-C6TUvUdVy8O9zFUh7kaYw5w,3865
|
@@ -102,7 +102,7 @@ reconcile/resource_template_tester.py,sha256=DsKvBuNLPxm4Fa-e1YHHySnhThm5i_j-nF3
|
|
102
102
|
reconcile/run_integration.py,sha256=8kc-lMKF9n2bvyrItJ-3nOgQMqK7lh1UAubXQrxQDPY,9711
|
103
103
|
reconcile/saas_file_validator.py,sha256=tyvFYU6lnkfDYIkAIr5pWqSvO5Yc6TagZ-quJYD2dtI,2547
|
104
104
|
reconcile/sendgrid_teammates.py,sha256=oO8QbLb4s1o8A6CGiCagN9CmS05BSS_WLztuY0Ym9D8,4773
|
105
|
-
reconcile/service_dependencies.py,sha256=
|
105
|
+
reconcile/service_dependencies.py,sha256=S8DOputtxAX-MXvWuTLEOsgLlVkXJHALODPSnWOpvGk,4500
|
106
106
|
reconcile/signalfx_endpoint_monitoring.py,sha256=Nqgsg1cflSd2nNnm89y_e8c--7xLUqTrKOHkDs-qADE,2868
|
107
107
|
reconcile/slack_base.py,sha256=I-msunWxfgu5bSwXYulGbtLjxUB_tRmTCAUCU-3nabI,3484
|
108
108
|
reconcile/slack_usergroups.py,sha256=vMifpbnrQDLeckGtUmpIg7sVvlhpaJz8HZH_loA7fpY,30221
|
@@ -482,11 +482,11 @@ reconcile/rhidp/sso_client/base.py,sha256=EfQ2ewcOKh5idg46UKAkY6z0m_nGQfvnQKffa2
|
|
482
482
|
reconcile/rhidp/sso_client/integration.py,sha256=kA8g7c38ZBSdrRtyfEqy_WgSreD1PbwY7ZIN-3tZRPc,2221
|
483
483
|
reconcile/rhidp/sso_client/metrics.py,sha256=Tq7tSOsqL3XdcPUdozxqzSPIodUeOV87UCTqpuuqqhw,1013
|
484
484
|
reconcile/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
485
|
-
reconcile/saas_auto_promotions_manager/integration.py,sha256=
|
485
|
+
reconcile/saas_auto_promotions_manager/integration.py,sha256=PhngUNVQMdZ_7KlIOCokdYqQ2k-XdsvvfCb8BAdSiAA,6889
|
486
486
|
reconcile/saas_auto_promotions_manager/meta.py,sha256=76Jp50r6Y_KyJoXFfSjrt5YrCtXyg_A4FXXxHYiS3TE,161
|
487
487
|
reconcile/saas_auto_promotions_manager/publisher.py,sha256=5gphMxr2NUvyB7WDK4eAbgZeyeF30cZ3a2ZGrbFQgZk,2976
|
488
488
|
reconcile/saas_auto_promotions_manager/s3_exporter.py,sha256=Y-r5R6viiAzglUHbYKItYSjT_axmLlPEJVmu_H6N170,2682
|
489
|
-
reconcile/saas_auto_promotions_manager/subscriber.py,sha256=
|
489
|
+
reconcile/saas_auto_promotions_manager/subscriber.py,sha256=V8e2tz0s3A-pcUNb2UoREQm6-6ZzS4F3gJdGUBoa9WY,11281
|
490
490
|
reconcile/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
491
491
|
reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py,sha256=R2CRtjdOggY5lSqt-A5qz2ymqomx4opVeVV_oqBAW0A,7804
|
492
492
|
reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py,sha256=isY8frVsL3PlcdZmdZ4O0qyp76oczl4DUMX9uMArs5Y,1222
|
@@ -497,7 +497,7 @@ reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py,sha256
|
|
497
497
|
reconcile/saas_auto_promotions_manager/merge_request_manager/open_merge_requests.py,sha256=-qGQOh6Jdp4lomNDij3zWVC0pl6uPHFWS5Woqcp5HQk,410
|
498
498
|
reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=EgImn9SpeThTNN5-P5lvz__bMKZNU4m2SfKpocRCy5w,7278
|
499
499
|
reconcile/saas_auto_promotions_manager/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
500
|
-
reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=
|
500
|
+
reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=BPzSsuXy5ULKSo36v1bItC3rU-AEFfVZeWXZw1tXqLg,9674
|
501
501
|
reconcile/skupper_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
502
502
|
reconcile/skupper_network/integration.py,sha256=oZIVDBRcQPC-lWxNFiJhGbtCM7Yj7fjwAzYZ8JvVe3I,10789
|
503
503
|
reconcile/skupper_network/models.py,sha256=HEwlVKsbmMaKaaBGvITIiSYNEVdjwXVhLaOJgLSZ2xQ,6604
|
@@ -569,7 +569,7 @@ reconcile/typed_queries/pagerduty_instances.py,sha256=zxCNxMak4iikryePaRi71lTADV
|
|
569
569
|
reconcile/typed_queries/quay.py,sha256=3IMy9jjHF2f9t47EXZOQVA3p0nFkWFhaFhxhvib-71o,644
|
570
570
|
reconcile/typed_queries/repos.py,sha256=8A93dKDt6igT4ClqMjt7YUTsoP4qh1Wnm0W3xsMgj48,824
|
571
571
|
reconcile/typed_queries/reserved_networks.py,sha256=XY9y3amtIQT0n06O0Toubqr_UmylJ2ELAv9-BJCK890,345
|
572
|
-
reconcile/typed_queries/saas_files.py,sha256=
|
572
|
+
reconcile/typed_queries/saas_files.py,sha256=SOE36sWPBcuaRmEaNxXCQZMQdJiUZX8_A92o42XwHQA,14141
|
573
573
|
reconcile/typed_queries/slack.py,sha256=r30lspctHloyygPn8_DVybxPwUWwiBpvBRRXiTVcQYk,251
|
574
574
|
reconcile/typed_queries/slo_documents.py,sha256=YMdox_-lBRqrdxamPhdnUlRTY_Ro35ptsupq7OaynUQ,362
|
575
575
|
reconcile/typed_queries/smtp.py,sha256=aSLglYa5bHKmlGwKkxq2RZqyMWuAf0a4S_mOuhDa084,542
|
@@ -616,7 +616,7 @@ reconcile/utils/external_resources.py,sha256=YzTb0xAcNdmKO326mGQy7BmST56CZcdru4l
|
|
616
616
|
reconcile/utils/filtering.py,sha256=S4PbMHuFr3ED0P2Q_ea5CAaB7FimI62B-F5YTaKrphA,402
|
617
617
|
reconcile/utils/git.py,sha256=o4p9m8jlzCJDcutl2HErvGLhL6sZ1NB4Aw3zGcQIzso,2427
|
618
618
|
reconcile/utils/github_api.py,sha256=o4J0ZU1ZSr9808uoorKHv19iae-eLo85yrCZX67p2kw,2822
|
619
|
-
reconcile/utils/gitlab_api.py,sha256=
|
619
|
+
reconcile/utils/gitlab_api.py,sha256=qQMN9JwaUvbirbLBy1BImkeJ4iFR-OCfWExphrfkmXs,28610
|
620
620
|
reconcile/utils/gpg.py,sha256=EKG7_fdMv8BMlV5yUdPiqoTx-KrzmVSEAl2sLkaKwWI,1123
|
621
621
|
reconcile/utils/gql.py,sha256=C0thIm_k9MBldfqwHzyqtYZk9sIvMdm9IbbnXLGwjD8,14158
|
622
622
|
reconcile/utils/grouping.py,sha256=vr9SFHZ7bqmHYrvYcEZt-Er3-yQYfAAdq5sHLZVmXPY,456
|
@@ -626,7 +626,7 @@ reconcile/utils/imap_client.py,sha256=h8YDiCSCvroErhpH_-KGYI7Y2WU2Q2oSpuxDFbOkSb
|
|
626
626
|
reconcile/utils/instrumented_wrappers.py,sha256=VqT4s0Bdicv224-uSeSaugtHXm-xJ3oSeBiqj0QQRiU,1942
|
627
627
|
reconcile/utils/jenkins_api.py,sha256=RaKuZmO7_lbI-hE6c_Pq2a6CQdmBVj7BcP2jR68cIbI,7081
|
628
628
|
reconcile/utils/jira_client.py,sha256=xhklHRsMnQqZ8WCxO1efjRKvx6diLcGQ6DLi5ZKl_HM,10544
|
629
|
-
reconcile/utils/jjb_client.py,sha256=
|
629
|
+
reconcile/utils/jjb_client.py,sha256=e5cDeNAeJMGz3sZMJ1KUIMFyLdRet0YnC0Qgj1vTPHc,15239
|
630
630
|
reconcile/utils/jsonpath.py,sha256=wdxOMqR-GMpQf5vRPWRMqAF7bCiXDBkkcFfY2U4j_tk,5536
|
631
631
|
reconcile/utils/jump_host.py,sha256=gi8vGUDgdTVwJvROvRVauFxtL0YAramhbWvG70L7AY8,5137
|
632
632
|
reconcile/utils/keycloak.py,sha256=YWSEUGrOVqFaJUk055dKUWpLDPdDRvhcmvR-lfbmxdE,3388
|
@@ -667,12 +667,12 @@ reconcile/utils/state.py,sha256=az4tBmZ0EdbFcAGiBVUxs3cr2-BVWsuDQiNTvjjQq8s,1637
|
|
667
667
|
reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
|
668
668
|
reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
|
669
669
|
reconcile/utils/terraform_client.py,sha256=IDlrNvGEc2i6ElZIL_fzaJEad1nRC3DkP9_VXhJXmU0,37329
|
670
|
-
reconcile/utils/terrascript_aws_client.py,sha256
|
670
|
+
reconcile/utils/terrascript_aws_client.py,sha256=-FNQXltzl4OYGO7eMyvH7-wYUMHNFEVhiNwCvhN6WrI,292307
|
671
671
|
reconcile/utils/three_way_diff_strategy.py,sha256=oQcHXd9LVhirJfoaOBoHUYuZVGfyL2voKr6KVI34zZE,4833
|
672
672
|
reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
|
673
673
|
reconcile/utils/vault.py,sha256=aSA8l9cJlPUHpChFGl27nSY-Mpq9FMjBo7Dcgb1BVfM,15036
|
674
674
|
reconcile/utils/vaultsecretref.py,sha256=0KUSzuvTRxPyKY919TO3-B_eYg4_76fzKvMF8j5s1G0,911
|
675
|
-
reconcile/utils/vcs.py,sha256=
|
675
|
+
reconcile/utils/vcs.py,sha256=_S_QZ5UYXOnhNDOBQ-jNVOB6VpYh7Y96YLsM5T3ivug,8836
|
676
676
|
reconcile/utils/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
677
677
|
reconcile/utils/acs/base.py,sha256=4UsDrCpAOuddL3PKNuIQYoJP1BtZQNNB8_KEX0lXneg,2532
|
678
678
|
reconcile/utils/acs/notifiers.py,sha256=DlzTDM9arWQlBSiDy70y5Mf38OKVs9V0FzFe2LfOKXA,5046
|
@@ -761,7 +761,7 @@ reconcile/utils/runtime/sharding.py,sha256=r0ieUtNed7NvknSw6qQrCkKpVXE1shuHGnfFc
|
|
761
761
|
reconcile/utils/saasherder/__init__.py,sha256=3U8plqMAPRE1kjwZ5YnIsYsggTf4_gS7flRUEuXVBAs,343
|
762
762
|
reconcile/utils/saasherder/interfaces.py,sha256=NEYQspYfyWQhBeJyNCqSFbixi1A4wRVGB7FeNM5BDCk,9141
|
763
763
|
reconcile/utils/saasherder/models.py,sha256=JaOz_DEtudJZhiDe90kaBlJkppFufn81V92oK9PHYx0,10208
|
764
|
-
reconcile/utils/saasherder/saasherder.py,sha256=
|
764
|
+
reconcile/utils/saasherder/saasherder.py,sha256=PjwJ36Eki5X0Wqu7-sE1slApMh6th3NojAWfZpOz_OQ,87111
|
765
765
|
reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
|
766
766
|
reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
|
767
767
|
reconcile/utils/terraform/config_client.py,sha256=gRL1rQ0AqvShei_rcGqC3HDYGskOFKE1nPrJyJE9yno,4676
|
@@ -807,7 +807,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
807
807
|
tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
|
808
808
|
tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
|
809
809
|
tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
|
810
|
-
qontract_reconcile-0.10.2.
|
811
|
-
qontract_reconcile-0.10.2.
|
812
|
-
qontract_reconcile-0.10.2.
|
813
|
-
qontract_reconcile-0.10.2.
|
810
|
+
qontract_reconcile-0.10.2.dev182.dist-info/METADATA,sha256=ykY9LybQBKkA6Trn_h7QDGXtheaf8sfn8XwOcno_Ev4,24627
|
811
|
+
qontract_reconcile-0.10.2.dev182.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
812
|
+
qontract_reconcile-0.10.2.dev182.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
813
|
+
qontract_reconcile-0.10.2.dev182.dist-info/RECORD,,
|
reconcile/dashdotdb_dora.py
CHANGED
@@ -34,6 +34,7 @@ from reconcile.typed_queries.saas_files import get_saas_files
|
|
34
34
|
from reconcile.utils.github_api import GithubRepositoryApi
|
35
35
|
from reconcile.utils.gitlab_api import GitLabApi
|
36
36
|
from reconcile.utils.secret_reader import create_secret_reader
|
37
|
+
from reconcile.utils.vcs import GITHUB_BASE_URL
|
37
38
|
|
38
39
|
QONTRACT_INTEGRATION = "dashdotdb-dora"
|
39
40
|
|
@@ -421,7 +422,7 @@ class DashdotdbDORA(DashdotdbBase):
|
|
421
422
|
return rc, []
|
422
423
|
|
423
424
|
LOG.info("Fetching commits %s", rc)
|
424
|
-
if rc.repo_url.startswith(
|
425
|
+
if rc.repo_url.startswith(GITHUB_BASE_URL):
|
425
426
|
try:
|
426
427
|
commits = self._github_compare_commits(rc)
|
427
428
|
except GithubException as e:
|
@@ -476,8 +477,7 @@ class DashdotdbDORA(DashdotdbBase):
|
|
476
477
|
if not rc.repo_url:
|
477
478
|
return []
|
478
479
|
|
479
|
-
|
480
|
-
repo = rc.repo_url[rc.repo_url.startswith(prefix) and len(prefix) :]
|
480
|
+
repo = rc.repo_url.removeprefix(GITHUB_BASE_URL).rstrip("/")
|
481
481
|
|
482
482
|
return [
|
483
483
|
Commit(rc.repo_url, commit.sha, commit.commit.committer.date)
|
@@ -11,6 +11,7 @@ from reconcile.jenkins_job_builder import init_jjb
|
|
11
11
|
from reconcile.utils.jjb_client import JJB
|
12
12
|
from reconcile.utils.secret_reader import SecretReader
|
13
13
|
from reconcile.utils.semver_helper import make_semver
|
14
|
+
from reconcile.utils.vcs import GITHUB_BASE_URL
|
14
15
|
|
15
16
|
QONTRACT_INTEGRATION = "github-repo-permissions-validator"
|
16
17
|
QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
|
@@ -45,7 +46,7 @@ def run(dry_run: bool, instance_name: str) -> None:
|
|
45
46
|
error = False
|
46
47
|
for job in pr_check_jobs:
|
47
48
|
repo_url = jjb.get_repo_url(job)
|
48
|
-
repo_name = repo_url.
|
49
|
+
repo_name = repo_url.removeprefix(GITHUB_BASE_URL).rstrip("/")
|
49
50
|
repo = gh.get_repo(repo_name)
|
50
51
|
permissions = repo.permissions
|
51
52
|
if not permissions.push and repo_url not in invitations:
|
@@ -47,6 +47,7 @@ from reconcile.utils.runtime.sharding import (
|
|
47
47
|
StaticShardingStrategy,
|
48
48
|
)
|
49
49
|
from reconcile.utils.semver_helper import make_semver
|
50
|
+
from reconcile.utils.vcs import GITHUB_BASE_URL
|
50
51
|
|
51
52
|
QONTRACT_INTEGRATION = "integrations-manager"
|
52
53
|
QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
|
@@ -58,8 +59,7 @@ INTEGRATION_UPSTREAM_REPOS_PARAM = "INTEGRATION_UPSTREAM_REPOS"
|
|
58
59
|
|
59
60
|
|
60
61
|
def get_image_tag_from_ref(ref: str, upstream: str) -> str:
|
61
|
-
|
62
|
-
upstream = upstream.removeprefix(gh_prefix)
|
62
|
+
upstream = upstream.removeprefix(GITHUB_BASE_URL)
|
63
63
|
settings = queries.get_app_interface_settings()
|
64
64
|
gh_token = get_default_config()["token"]
|
65
65
|
github = Github(gh_token, base_url=GH_BASE_URL)
|
@@ -94,6 +94,7 @@ class SaasAutoPromotionsManager:
|
|
94
94
|
|
95
95
|
def init_external_dependencies(
|
96
96
|
dry_run: bool,
|
97
|
+
thread_pool_size: int,
|
97
98
|
env_name: str | None = None,
|
98
99
|
app_name: str | None = None,
|
99
100
|
) -> tuple[
|
@@ -139,7 +140,11 @@ def init_external_dependencies(
|
|
139
140
|
renderer=Renderer(),
|
140
141
|
)
|
141
142
|
saas_files = get_saas_files(env_name=env_name, app_name=app_name)
|
142
|
-
saas_inventory = SaasFilesInventory(
|
143
|
+
saas_inventory = SaasFilesInventory(
|
144
|
+
saas_files=saas_files,
|
145
|
+
secret_reader=secret_reader,
|
146
|
+
thread_pool_size=thread_pool_size,
|
147
|
+
)
|
143
148
|
saas_deploy_state = init_state(
|
144
149
|
integration=OPENSHIFT_SAAS_DEPLOY, secret_reader=secret_reader
|
145
150
|
)
|
@@ -181,7 +186,10 @@ def run(
|
|
181
186
|
saas_deploy_state,
|
182
187
|
sapm_state,
|
183
188
|
) = init_external_dependencies(
|
184
|
-
dry_run=dry_run,
|
189
|
+
dry_run=dry_run,
|
190
|
+
env_name=env_name,
|
191
|
+
app_name=app_name,
|
192
|
+
thread_pool_size=thread_pool_size,
|
185
193
|
)
|
186
194
|
if defer:
|
187
195
|
defer(vcs.cleanup)
|
@@ -13,6 +13,7 @@ from reconcile.saas_auto_promotions_manager.publisher import (
|
|
13
13
|
DeploymentInfo,
|
14
14
|
Publisher,
|
15
15
|
)
|
16
|
+
from reconcile.utils.slo_document_manager import SLODocumentManager
|
16
17
|
|
17
18
|
CONTENT_HASH_LENGTH = 32
|
18
19
|
|
@@ -47,7 +48,9 @@ class Subscriber:
|
|
47
48
|
uid: str,
|
48
49
|
soak_days: int,
|
49
50
|
blocked_versions: set[str],
|
51
|
+
hotfix_versions: set[str],
|
50
52
|
schedule: str,
|
53
|
+
slo_document_manager: SLODocumentManager | None = None,
|
51
54
|
):
|
52
55
|
self.saas_name = saas_name
|
53
56
|
self.template_name = template_name
|
@@ -64,6 +67,8 @@ class Subscriber:
|
|
64
67
|
self._content_hash = ""
|
65
68
|
self._use_target_config_hash = use_target_config_hash
|
66
69
|
self._blocked_versions = blocked_versions
|
70
|
+
self._hotfix_versions = hotfix_versions
|
71
|
+
self.slo_document_manager = slo_document_manager
|
67
72
|
|
68
73
|
def has_diff(self) -> bool:
|
69
74
|
current_hashes = {
|
@@ -192,6 +197,10 @@ class Subscriber:
|
|
192
197
|
return
|
193
198
|
|
194
199
|
desired_ref = next(iter(publisher_refs))
|
200
|
+
# validate slo gatekeeping
|
201
|
+
if self._has_breached_slos(desired_ref=desired_ref):
|
202
|
+
return
|
203
|
+
|
195
204
|
if desired_ref in self._blocked_versions:
|
196
205
|
logging.info(
|
197
206
|
"Subscriber at path %s promotion stopped because of blocked ref: %s",
|
@@ -203,6 +212,25 @@ class Subscriber:
|
|
203
212
|
# Passed all gates -> lets promote desired ref
|
204
213
|
self.desired_ref = desired_ref
|
205
214
|
|
215
|
+
def _has_breached_slos(self, desired_ref: str) -> bool:
|
216
|
+
if self.slo_document_manager and desired_ref not in self._hotfix_versions:
|
217
|
+
breached_slos = self.slo_document_manager.get_breached_slos()
|
218
|
+
if breached_slos:
|
219
|
+
logging.info(
|
220
|
+
"Subscriber at path %s promotion stopped because following breached SLOs",
|
221
|
+
self.target_file_path,
|
222
|
+
)
|
223
|
+
for slo in breached_slos:
|
224
|
+
logging.info(
|
225
|
+
"SLO:%s of document %s is breached. Current value:%f Expected:%f ",
|
226
|
+
slo.slo.name,
|
227
|
+
slo.slo_document_name,
|
228
|
+
slo.current_slo_value,
|
229
|
+
slo.slo.slo_target,
|
230
|
+
)
|
231
|
+
return True
|
232
|
+
return False
|
233
|
+
|
206
234
|
def _compute_desired_config_hashes(self) -> None:
|
207
235
|
"""
|
208
236
|
Compute the desired config hashes for this subscriber.
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import logging
|
2
|
+
from collections import defaultdict
|
2
3
|
from collections.abc import Iterable
|
3
4
|
|
4
5
|
from reconcile.gql_definitions.common.saas_files import ParentSaasPromotionV1
|
@@ -8,7 +9,9 @@ from reconcile.saas_auto_promotions_manager.subscriber import (
|
|
8
9
|
ConfigHash,
|
9
10
|
Subscriber,
|
10
11
|
)
|
11
|
-
from reconcile.typed_queries.saas_files import SaasFile
|
12
|
+
from reconcile.typed_queries.saas_files import SaasFile, SaasResourceTemplateTarget
|
13
|
+
from reconcile.utils.secret_reader import SecretReaderBase
|
14
|
+
from reconcile.utils.slo_document_manager import SLODocumentManager
|
12
15
|
|
13
16
|
|
14
17
|
class SaasFileInventoryError(Exception):
|
@@ -25,8 +28,15 @@ class SaasFilesInventory:
|
|
25
28
|
This basically spans a directed graph, with subscribers as the root.
|
26
29
|
"""
|
27
30
|
|
28
|
-
def __init__(
|
31
|
+
def __init__(
|
32
|
+
self,
|
33
|
+
saas_files: Iterable[SaasFile],
|
34
|
+
secret_reader: SecretReaderBase,
|
35
|
+
thread_pool_size: int,
|
36
|
+
):
|
29
37
|
self._saas_files = saas_files
|
38
|
+
self.secret_reader = secret_reader
|
39
|
+
self.thread_pool_size = thread_pool_size
|
30
40
|
self._channels_by_name: dict[str, Channel] = {}
|
31
41
|
self.subscribers: list[Subscriber] = []
|
32
42
|
self.publishers: list[Publisher] = []
|
@@ -86,10 +96,13 @@ class SaasFilesInventory:
|
|
86
96
|
|
87
97
|
def _assemble_subscribers_with_auto_promotions(self) -> None:
|
88
98
|
for saas_file in self._saas_files:
|
89
|
-
blocked_versions: dict[str, set[str]] =
|
99
|
+
blocked_versions: dict[str, set[str]] = defaultdict(set[str])
|
100
|
+
hotfix_versions: dict[str, set[str]] = defaultdict(set[str])
|
90
101
|
for code_component in saas_file.app.code_components or []:
|
91
102
|
for version in code_component.blocked_versions or []:
|
92
|
-
blocked_versions
|
103
|
+
blocked_versions[code_component.url].add(version)
|
104
|
+
for hf_version in code_component.hotfix_versions or []:
|
105
|
+
hotfix_versions[code_component.url].add(hf_version)
|
93
106
|
for resource_template in saas_file.resource_templates:
|
94
107
|
for target in resource_template.targets:
|
95
108
|
file_path = target.path or saas_file.path
|
@@ -101,6 +114,7 @@ class SaasFilesInventory:
|
|
101
114
|
continue
|
102
115
|
soak_days = target.promotion.soak_days or 0
|
103
116
|
schedule = target.promotion.schedule or "* * * * *"
|
117
|
+
|
104
118
|
subscriber = Subscriber(
|
105
119
|
uid=target.uid(
|
106
120
|
parent_saas_file_name=saas_file.name,
|
@@ -112,10 +126,10 @@ class SaasFilesInventory:
|
|
112
126
|
ref=target.ref,
|
113
127
|
target_namespace=target.namespace,
|
114
128
|
soak_days=soak_days,
|
129
|
+
slo_document_manager=self._build_slo_document_manager(target),
|
115
130
|
schedule=schedule,
|
116
|
-
|
117
|
-
|
118
|
-
),
|
131
|
+
hotfix_versions=hotfix_versions[resource_template.url],
|
132
|
+
blocked_versions=blocked_versions[resource_template.url],
|
119
133
|
use_target_config_hash=bool(
|
120
134
|
target.promotion.redeploy_on_publisher_config_change
|
121
135
|
),
|
@@ -158,6 +172,17 @@ class SaasFilesInventory:
|
|
158
172
|
self._channels_by_name[subscribe_channel]
|
159
173
|
)
|
160
174
|
|
175
|
+
def _build_slo_document_manager(
|
176
|
+
self, target: SaasResourceTemplateTarget
|
177
|
+
) -> SLODocumentManager | None:
|
178
|
+
if target.slos:
|
179
|
+
return SLODocumentManager(
|
180
|
+
slo_documents=target.slos,
|
181
|
+
secret_reader=self.secret_reader,
|
182
|
+
thread_pool_size=self.thread_pool_size,
|
183
|
+
)
|
184
|
+
return None
|
185
|
+
|
161
186
|
def _remove_unsupported(self) -> None:
|
162
187
|
"""
|
163
188
|
Lets remove subscribers from which we know we do not support them and log an error.
|
@@ -16,6 +16,7 @@ from reconcile.gql_definitions.service_dependencies.service_dependencies import
|
|
16
16
|
SaasResourceTemplateV2,
|
17
17
|
)
|
18
18
|
from reconcile.utils import gql
|
19
|
+
from reconcile.utils.vcs import GITHUB_BASE_URL
|
19
20
|
|
20
21
|
QONTRACT_INTEGRATION = "service-dependencies"
|
21
22
|
|
@@ -35,7 +36,9 @@ def get_desired_dependency_names(
|
|
35
36
|
gitlab_urls = [cc for cc in code_components if "gitlab" in cc.url]
|
36
37
|
if gitlab_urls:
|
37
38
|
required_dep_names.update(get_dependency_names(dependency_map, "gitlab"))
|
38
|
-
github_urls = [
|
39
|
+
github_urls = [
|
40
|
+
cc for cc in code_components if cc.url.startswith(GITHUB_BASE_URL)
|
41
|
+
]
|
39
42
|
if github_urls:
|
40
43
|
required_dep_names.update(get_dependency_names(dependency_map, "github"))
|
41
44
|
|
@@ -39,6 +39,7 @@ from reconcile.gql_definitions.common.saasherder_settings import AppInterfaceSet
|
|
39
39
|
from reconcile.gql_definitions.common.saasherder_settings import (
|
40
40
|
query as saasherder_settings_query,
|
41
41
|
)
|
42
|
+
from reconcile.gql_definitions.fragments.saas_slo_document import SLODocument
|
42
43
|
from reconcile.gql_definitions.fragments.saas_target_namespace import (
|
43
44
|
SaasTargetNamespace,
|
44
45
|
)
|
@@ -63,6 +64,7 @@ class SaasResourceTemplateTarget(ConfiguredBaseModel):
|
|
63
64
|
secret_parameters: (
|
64
65
|
list[SaasResourceTemplateTargetV2_SaasSecretParametersV1] | None
|
65
66
|
) = Field(..., alias="secretParameters")
|
67
|
+
slos: list[SLODocument] | None = Field(..., alias="slos")
|
66
68
|
upstream: SaasResourceTemplateTargetUpstreamV1 | None = Field(..., alias="upstream")
|
67
69
|
images: list[SaasResourceTemplateTargetImageV1] | None = Field(..., alias="images")
|
68
70
|
disable: bool | None = Field(..., alias="disable")
|
reconcile/utils/gitlab_api.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
import io
|
1
2
|
import logging
|
2
3
|
import os
|
3
4
|
import re
|
5
|
+
import tarfile
|
4
6
|
from collections.abc import (
|
5
7
|
Iterable,
|
6
8
|
Mapping,
|
@@ -828,3 +830,29 @@ class GitLabApi:
|
|
828
830
|
list[PersonalAccessToken],
|
829
831
|
self.gl.personal_access_tokens.list(get_all=True),
|
830
832
|
)
|
833
|
+
|
834
|
+
@staticmethod
|
835
|
+
def get_directory_contents(
|
836
|
+
project: Project,
|
837
|
+
ref: str | None = None,
|
838
|
+
path: str | None = None,
|
839
|
+
) -> dict[str, bytes]:
|
840
|
+
"""
|
841
|
+
Get the contents of a directory in a project.
|
842
|
+
|
843
|
+
:param project: The project to get the contents from.
|
844
|
+
:param ref: The commit SHA to download. A tag, branch reference, or SHA can be used. If not specified, defaults to the tip of the default branch.
|
845
|
+
:param path: The subpath of the repository to download. If an empty string, defaults to the whole repository.
|
846
|
+
:return: A dictionary with the file path as keys and the file content bytes as values.
|
847
|
+
"""
|
848
|
+
archive = project.repository_archive(format="tar.gz", sha=ref, path=path)
|
849
|
+
tar_bytes = io.BytesIO(archive)
|
850
|
+
with tarfile.open(fileobj=tar_bytes, mode="r:gz") as tar:
|
851
|
+
return {
|
852
|
+
file_path: file.read()
|
853
|
+
for member in tar.getmembers()
|
854
|
+
if member.isfile()
|
855
|
+
# skip leading prefix xxx/
|
856
|
+
and (file_path := member.name.split("/", 1)[-1])
|
857
|
+
and (file := tar.extractfile(member))
|
858
|
+
}
|
reconcile/utils/jjb_client.py
CHANGED
@@ -25,6 +25,7 @@ from sretoolbox.utils import retry
|
|
25
25
|
|
26
26
|
from reconcile.utils import throughput
|
27
27
|
from reconcile.utils.helpers import toggle_logger
|
28
|
+
from reconcile.utils.vcs import GITHUB_BASE_URL
|
28
29
|
|
29
30
|
JJB_INI = "[jenkins]\nurl = https://JENKINS_URL"
|
30
31
|
|
@@ -290,7 +291,7 @@ class JJB: # pylint: disable=too-many-public-methods
|
|
290
291
|
for job in jobs:
|
291
292
|
try:
|
292
293
|
project_url_raw = job["properties"][0]["github"]["url"]
|
293
|
-
if
|
294
|
+
if project_url_raw.startswith(GITHUB_BASE_URL):
|
294
295
|
continue
|
295
296
|
if str(job.get("disabled")).lower() == "true":
|
296
297
|
continue
|
@@ -83,6 +83,7 @@ from reconcile.utils.saasherder.models import (
|
|
83
83
|
)
|
84
84
|
from reconcile.utils.secret_reader import SecretReaderBase
|
85
85
|
from reconcile.utils.state import State
|
86
|
+
from reconcile.utils.vcs import GITHUB_BASE_URL
|
86
87
|
|
87
88
|
TARGET_CONFIG_HASH = "target_config_hash"
|
88
89
|
|
@@ -742,7 +743,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
742
743
|
[url, sha] = trigger_reason.split(" ")[0].split("/commit/")
|
743
744
|
repo_name = urlparse(url).path.strip("/")
|
744
745
|
file_name = f"{repo_name.replace('/', '-')}-{sha}.tar.gz"
|
745
|
-
if
|
746
|
+
if url.startswith(GITHUB_BASE_URL):
|
746
747
|
github = self._initiate_github(saas_file, base_url="https://api.github.com")
|
747
748
|
repo = github.get_repo(repo_name)
|
748
749
|
# get_archive_link get redirect url form header, it does not work with github-mirror
|
@@ -760,8 +761,8 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
760
761
|
) -> tuple[Any, str]:
|
761
762
|
commit_sha = self._get_commit_sha(url, ref, github)
|
762
763
|
|
763
|
-
if
|
764
|
-
repo_name = url.
|
764
|
+
if url.startswith(GITHUB_BASE_URL):
|
765
|
+
repo_name = url.removeprefix(GITHUB_BASE_URL).rstrip("/")
|
765
766
|
repo = github.get_repo(repo_name)
|
766
767
|
content = self._get_file_contents_github(repo, path, commit_sha)
|
767
768
|
elif "gitlab" in url:
|
@@ -781,8 +782,8 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
781
782
|
) -> tuple[list[Any], str]:
|
782
783
|
commit_sha = self._get_commit_sha(url, ref, github)
|
783
784
|
resources: list[Any] = []
|
784
|
-
if
|
785
|
-
repo_name = url.
|
785
|
+
if url.startswith(GITHUB_BASE_URL):
|
786
|
+
repo_name = url.removeprefix(GITHUB_BASE_URL).rstrip("/")
|
786
787
|
repo = github.get_repo(repo_name)
|
787
788
|
directory = repo.get_contents(path, commit_sha)
|
788
789
|
if isinstance(directory, ContentFile):
|
@@ -798,17 +799,14 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
798
799
|
if not self.gitlab:
|
799
800
|
raise Exception("gitlab is not initialized")
|
800
801
|
project = self.gitlab.get_project(url)
|
801
|
-
|
802
|
-
project
|
803
|
-
path=path.lstrip("/"),
|
802
|
+
dir_contents = self.gitlab.get_directory_contents(
|
803
|
+
project,
|
804
804
|
ref=commit_sha,
|
805
|
-
|
806
|
-
)
|
807
|
-
|
808
|
-
|
809
|
-
)
|
810
|
-
resource = yaml.safe_load(file_contents.decode())
|
811
|
-
resources.append(resource)
|
805
|
+
path=path,
|
806
|
+
)
|
807
|
+
for content in dir_contents.values():
|
808
|
+
result_resources = yaml.safe_load_all(content)
|
809
|
+
resources.extend(result_resources)
|
812
810
|
else:
|
813
811
|
raise Exception(f"Only GitHub and GitLab are supported: {url}")
|
814
812
|
|
@@ -817,8 +815,8 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
817
815
|
@retry()
|
818
816
|
def _get_commit_sha(self, url: str, ref: str, github: Github) -> str:
|
819
817
|
commit_sha = ""
|
820
|
-
if
|
821
|
-
repo_name = url.
|
818
|
+
if url.startswith(GITHUB_BASE_URL):
|
819
|
+
repo_name = url.removeprefix(GITHUB_BASE_URL).rstrip("/")
|
822
820
|
repo = github.get_repo(repo_name)
|
823
821
|
commit = repo.get_commit(sha=ref)
|
824
822
|
commit_sha = commit.sha
|
@@ -186,6 +186,7 @@ from reconcile.utils.password_validator import (
|
|
186
186
|
)
|
187
187
|
from reconcile.utils.secret_reader import SecretReader, SecretReaderBase
|
188
188
|
from reconcile.utils.terraform import safe_resource_id
|
189
|
+
from reconcile.utils.vcs import GITHUB_BASE_URL
|
189
190
|
|
190
191
|
GH_BASE_URL = os.environ.get("GITHUB_API", "https://api.github.com")
|
191
192
|
LOGTOES_RELEASE = "repos/app-sre/logs-to-elasticsearch-lambda/releases/latest"
|
@@ -5685,9 +5686,9 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
5685
5686
|
return ref
|
5686
5687
|
|
5687
5688
|
# get commit_sha from branch
|
5688
|
-
if
|
5689
|
+
if url.startswith(GITHUB_BASE_URL):
|
5689
5690
|
github = self.init_github()
|
5690
|
-
repo_name = url.
|
5691
|
+
repo_name = url.removeprefix(GITHUB_BASE_URL).rstrip("/")
|
5691
5692
|
repo = github.get_repo(repo_name)
|
5692
5693
|
commit = repo.get_commit(sha=ref)
|
5693
5694
|
return commit.sha
|
reconcile/utils/vcs.py
CHANGED
@@ -22,6 +22,8 @@ from reconcile.utils.secret_reader import (
|
|
22
22
|
SecretReaderBase,
|
23
23
|
)
|
24
24
|
|
25
|
+
GITHUB_BASE_URL = "https://github.com/"
|
26
|
+
|
25
27
|
|
26
28
|
class MRCheckStatus(Enum):
|
27
29
|
NONE = 0
|
@@ -158,7 +160,7 @@ class VCS:
|
|
158
160
|
) -> str:
|
159
161
|
if bool(self._is_commit_sha_regex.search(ref)):
|
160
162
|
return ref
|
161
|
-
if repo_url.startswith(
|
163
|
+
if repo_url.startswith(GITHUB_BASE_URL):
|
162
164
|
github = self._init_github(repo_url=repo_url, auth_code=auth_code)
|
163
165
|
return github.get_commit_sha(ref=ref)
|
164
166
|
# assume gitlab by default
|
@@ -175,7 +177,7 @@ class VCS:
|
|
175
177
|
Return a list of commits between two commits.
|
176
178
|
Note, that the commit_to is included in the result list, whereas commit_from is not included.
|
177
179
|
"""
|
178
|
-
if repo_url.startswith(
|
180
|
+
if repo_url.startswith(GITHUB_BASE_URL):
|
179
181
|
github = self._init_github(repo_url=repo_url, auth_code=auth_code)
|
180
182
|
data = github.compare(commit_from=commit_from, commit_to=commit_to)
|
181
183
|
return [
|
{qontract_reconcile-0.10.2.dev180.dist-info → qontract_reconcile-0.10.2.dev182.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|