qontract-reconcile 0.10.2.dev159__py3-none-any.whl → 0.10.2.dev173__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 (35) hide show
  1. {qontract_reconcile-0.10.2.dev159.dist-info → qontract_reconcile-0.10.2.dev173.dist-info}/METADATA +2 -2
  2. {qontract_reconcile-0.10.2.dev159.dist-info → qontract_reconcile-0.10.2.dev173.dist-info}/RECORD +34 -24
  3. reconcile/acs_rbac.py +1 -0
  4. reconcile/aws_cloudwatch_log_retention/integration.py +39 -25
  5. reconcile/cli.py +4 -6
  6. reconcile/dashdotdb_slo.py +45 -156
  7. reconcile/gcp_image_mirror.py +252 -0
  8. reconcile/gitlab_housekeeping.py +1 -1
  9. reconcile/gql_definitions/aws_cloudwatch_log_retention/__init__.py +0 -0
  10. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +158 -0
  11. reconcile/gql_definitions/common/saas_files.py +49 -0
  12. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +15 -67
  13. reconcile/gql_definitions/fragments/container_image_mirror.py +33 -0
  14. reconcile/gql_definitions/fragments/saas_slo_document.py +82 -0
  15. reconcile/gql_definitions/gcp/__init__.py +0 -0
  16. reconcile/gql_definitions/gcp/gcp_docker_repos.py +128 -0
  17. reconcile/gql_definitions/gcp/gcp_projects.py +77 -0
  18. reconcile/gql_definitions/introspection.json +380 -230
  19. reconcile/quay_mirror.py +3 -42
  20. reconcile/quay_mirror_org.py +3 -2
  21. reconcile/slack_base.py +2 -2
  22. reconcile/typed_queries/aws_cloudwatch_log_retention/aws_accounts.py +12 -0
  23. reconcile/utils/dynatrace/client.py +0 -31
  24. reconcile/utils/quay_mirror.py +42 -0
  25. reconcile/utils/saasherder/interfaces.py +2 -0
  26. reconcile/utils/saasherder/saasherder.py +5 -0
  27. reconcile/utils/slack_api.py +3 -1
  28. reconcile/utils/slo_document_manager.py +278 -0
  29. reconcile/utils/terrascript_aws_client.py +57 -0
  30. tools/{sd_app_sre_alert_report.py → alert_report.py} +1 -1
  31. tools/cli_commands/erv2.py +61 -0
  32. tools/qontract_cli.py +15 -5
  33. reconcile/gcr_mirror.py +0 -278
  34. {qontract_reconcile-0.10.2.dev159.dist-info → qontract_reconcile-0.10.2.dev173.dist-info}/WHEEL +0 -0
  35. {qontract_reconcile-0.10.2.dev159.dist-info → qontract_reconcile-0.10.2.dev173.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev159
3
+ Version: 0.10.2.dev173
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
@@ -20,7 +20,7 @@ Requires-Dist: croniter<1.1.0,>=1.0.15
20
20
  Requires-Dist: dateparser~=1.1.7
21
21
  Requires-Dist: deepdiff==6.7.1
22
22
  Requires-Dist: dnspython~=2.1
23
- Requires-Dist: dt==1.1.61
23
+ Requires-Dist: dt==1.1.73
24
24
  Requires-Dist: filetype~=1.2.0
25
25
  Requires-Dist: gql==3.1.0
26
26
  Requires-Dist: hvac<0.8.0,>=0.7.0
@@ -1,7 +1,7 @@
1
1
  reconcile/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  reconcile/acs_notifiers.py,sha256=YIV9TrgWjBD8nFbrBvvU8-9s-AdezY4X5t90bFROCtM,4451
3
3
  reconcile/acs_policies.py,sha256=xNbhIlwE1u2URbEQcX-3C-pTu--XjrKAqGj0-Wd85dY,9152
4
- reconcile/acs_rbac.py,sha256=hOQNOzD9f2Nioxb9XlspqnpZXH1DurCTnMcJpgyeB4E,22598
4
+ reconcile/acs_rbac.py,sha256=15vNfNzdG_DeXaJ-f5m8DSaJh__LUK766_xAECqyTsg,22657
5
5
  reconcile/aws_ami_share.py,sha256=M_gT7y3cSAyT_Pm90PBCNDSmbZtqREqe2jNETh0i9Qs,3808
6
6
  reconcile/aws_ecr_image_pull_secrets.py,sha256=F58PtX1GlB9XHqj8hGy9ItiTznXLAAKTNlWD9iT2MWI,2593
7
7
  reconcile/aws_garbage_collector.py,sha256=PG_0qccQIW347WhdLAhfT9x0P9Mq_ojacvSy5vbJWj8,471
@@ -10,19 +10,19 @@ reconcile/aws_iam_password_reset.py,sha256=O0JX2N5kNRKs3u2xzu4NNrI6p0ag5JWy3MTsv
10
10
  reconcile/aws_support_cases_sos.py,sha256=PDhilxQ4TBxVnxUPIUdTbKEaNUI0wzPiEsB91oHT2fY,3384
11
11
  reconcile/blackbox_exporter_endpoint_monitoring.py,sha256=O1wFp52EyF538c6txaWBs8eMtUIy19gyHZ6VzJ6QXS8,3512
12
12
  reconcile/checkpoint.py,sha256=_JhMxrye5BgkRMxWYuf7Upli6XayPINKSsuo3ynHTRc,5010
13
- reconcile/cli.py,sha256=hwqPcZVmazrhzq1esPBk5jNHSzpfr7o9EmuuMqiPxfg,108430
13
+ reconcile/cli.py,sha256=xyVnxNyq3IPISWwFlB9j4HAFjowXYv3EdsEGIMFhTy0,108438
14
14
  reconcile/closedbox_endpoint_monitoring_base.py,sha256=al7m8EgnnYx90rY1REryW3byN_ItfJfAzEeLtjbCfi0,4921
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
18
  reconcile/dashdotdb_dora.py,sha256=olQnGp4JYpoh1lQEf9kHc2y3bMaAIUXEB6eFohWH8Io,17859
19
19
  reconcile/dashdotdb_dvo.py,sha256=lCkZ0iby6HrNQb-3kYb6xrt8wCjVUZYxKzz9SiStfHU,8946
20
- reconcile/dashdotdb_slo.py,sha256=PU1GzT6Uy07IIO3Y62cFfRfaBJYUPrMkMp71Up80_bg,8334
20
+ reconcile/dashdotdb_slo.py,sha256=TvKdMOtUZcZP9QydcUJMKh0zURHgOMN_RTpQpCkD1Z8,3960
21
21
  reconcile/database_access_manager.py,sha256=Z3aAmw2LsmMIIor-bOGzziVZdVNC82Gmw8oHBUAFf-8,25577
22
22
  reconcile/deadmanssnitch.py,sha256=n-5W-djUgwzpmdDM4eQIZpkkDmHY0vndt-42LJXI4Y8,7491
23
23
  reconcile/email_sender.py,sha256=38Wvl6WHqCwlqLx4oxVJOIeDmoJsyitD3g1F4jTkAj8,4246
24
24
  reconcile/gabi_authorized_users.py,sha256=Jwvo97nzUX3NIl2VHKuZlT0-I40qk2VnACbafe91T2o,4854
25
- reconcile/gcr_mirror.py,sha256=cdTd0CZU0qUsXJqe5k4dgpMQlyk__nyeGH0f_Cky3C0,8957
25
+ reconcile/gcp_image_mirror.py,sha256=1ThuUff_04ZdF6uxcLoDuHhoNA3OIw0V-z0-CwdPE2w,9538
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
@@ -30,7 +30,7 @@ reconcile/github_repo_permissions_validator.py,sha256=DsM5IdEw3HvrpSRR9ZYjOLwE7Q
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
33
- reconcile/gitlab_housekeeping.py,sha256=Gy1mhn33xGp9IyQFqs4VrBmhwJBD6x90XITDR_pU4MU,25416
33
+ reconcile/gitlab_housekeeping.py,sha256=c31Jtw5t8bnOzUO9jMWF_0DHitPzol93AA7YWBxM5L0,25416
34
34
  reconcile/gitlab_labeler.py,sha256=BA2dbXsN9hErUwJl22qcxfeH7XiPCuQ9LN3NddWdnpo,4540
35
35
  reconcile/gitlab_members.py,sha256=MUIgYDLeJx2-_vMypyq2Pa17cpKdXATYhtVACS2ghpQ,8297
36
36
  reconcile/gitlab_mr_sqs_consumer.py,sha256=i_MDVfA3Uk_TJiNkfEJzhO6_rwR7z3I3dH9oEw686U4,2681
@@ -90,8 +90,8 @@ reconcile/openshift_users.py,sha256=JUWLb13USlQ4KvXZVsi3JES4csZnXlH0plhxskg_p6A,
90
90
  reconcile/openshift_vault_secrets.py,sha256=9rTqV6wzCQx2Oh712E_Xj8wMG7u8Oh-pY8DWjlv4mZw,1660
91
91
  reconcile/quay_base.py,sha256=h5xNjb7EZm8L2JgpO42r6w0UA4im5dabZXJSIW69zKU,1987
92
92
  reconcile/quay_membership.py,sha256=cmeoRdr3-wVlymNHVhzhW0W-Tq6qt1hd2OOIhGXsmrY,6398
93
- reconcile/quay_mirror.py,sha256=0KtQFwrvMNtlsPJ9F_-ICaVIjgIUjFxqipvAPcvyg3Q,15338
94
- reconcile/quay_mirror_org.py,sha256=tXKuF6JtmaNRwu8_g_65U_Vpd6sFBYeXmJA-flVhylE,10764
93
+ reconcile/quay_mirror.py,sha256=PBooiA0ShZpWYfO6oeKFqYYT6Syi7Q8JJD9kj0wRRLg,14030
94
+ reconcile/quay_mirror_org.py,sha256=I-tEqRHLL6uFqbSi7qCfPuDNoae7EAI2U68NbDOhmv8,10809
95
95
  reconcile/quay_permissions.py,sha256=9KOutS1w4RFQqkvMSy54VtsKNx56-phzP6yI_rEW-B8,4244
96
96
  reconcile/quay_repos.py,sha256=cuEYG0HUe0ut5yvLdEwOF5-CmccpXQHRb_wDazvDrvQ,6895
97
97
  reconcile/queries.py,sha256=JbkF6F13xdToj1WgWzkK7aU1Gf_gFbjuJvdsyQrZ1iw,50905
@@ -104,7 +104,7 @@ reconcile/saas_file_validator.py,sha256=tyvFYU6lnkfDYIkAIr5pWqSvO5Yc6TagZ-quJYD2
104
104
  reconcile/sendgrid_teammates.py,sha256=oO8QbLb4s1o8A6CGiCagN9CmS05BSS_WLztuY0Ym9D8,4773
105
105
  reconcile/service_dependencies.py,sha256=SOSJvSo6GchQpLsTbkGFnf1yHtlSFu2VnirAfi6-XGA,4418
106
106
  reconcile/signalfx_endpoint_monitoring.py,sha256=Nqgsg1cflSd2nNnm89y_e8c--7xLUqTrKOHkDs-qADE,2868
107
- reconcile/slack_base.py,sha256=8FqwMJ5SkoRyDJ9iPfZogWkC9QRoTouMCnGUevV_GME,3447
107
+ reconcile/slack_base.py,sha256=I-msunWxfgu5bSwXYulGbtLjxUB_tRmTCAUCU-3nabI,3484
108
108
  reconcile/slack_usergroups.py,sha256=vMifpbnrQDLeckGtUmpIg7sVvlhpaJz8HZH_loA7fpY,30221
109
109
  reconcile/sql_query.py,sha256=OEzEZaqgv-kzG3GR2x9w3uMIfSFXP6EdhlW4u5mc1Dg,25895
110
110
  reconcile/status.py,sha256=cY4IJFXemhxptRJqR4qaaOWqei9e4jgLXuVSGajMsjg,544
@@ -152,7 +152,7 @@ reconcile/aws_account_manager/utils.py,sha256=iYPPOtbZ7FiKkz9v5f1YXRIHw5YFOtSavU
152
152
  reconcile/aws_ami_cleanup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
153
  reconcile/aws_ami_cleanup/integration.py,sha256=KG7g9NpbKmoaveDD3oi9SinqUE29NaM-4lGo-6YuHlM,9302
154
154
  reconcile/aws_cloudwatch_log_retention/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
155
- reconcile/aws_cloudwatch_log_retention/integration.py,sha256=qVggTjGwP_6xTCXo2o3brSPtjwArNhZiGPy8YiBrCMM,7779
155
+ reconcile/aws_cloudwatch_log_retention/integration.py,sha256=QY5EtCpcMN0TgOQInIDW65wT1YksMBFkK8aNK5cg-XA,8107
156
156
  reconcile/aws_saml_idp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
157
  reconcile/aws_saml_idp/integration.py,sha256=Z2JtUx2YIbkn0KVrVa2CoAErPB8vTykOOkWD_ZPoB94,6511
158
158
  reconcile/aws_saml_roles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -227,7 +227,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=BgMx-NyV9mTuv7Sotb2OioC
227
227
  reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
228
  reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
229
229
  reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
- reconcile/gql_definitions/introspection.json,sha256=myUuHC_BLY3xZ0nDjnaQsvYFNM5eTiE3bWgNgM3e5iI,2290863
230
+ reconcile/gql_definitions/introspection.json,sha256=zD5QWpv9KYduZHr8a6dFoGz-oSHM1ItN1Trn02Lh7XQ,2297479
231
231
  reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
232
232
  reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
233
233
  reconcile/gql_definitions/acs/acs_policies.py,sha256=bN5i4mks10Z23KJSj7jqp966Osq2dps4d-sPH9gjxEA,7008
@@ -246,6 +246,8 @@ reconcile/gql_definitions/aws_account_manager/__init__.py,sha256=47DEQpj8HBSa-_T
246
246
  reconcile/gql_definitions/aws_account_manager/aws_accounts.py,sha256=vF51KrY2gwX0J9vESiaRMPQqdAMEtz9f_tBq52bInp0,5148
247
247
  reconcile/gql_definitions/aws_ami_cleanup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
248
248
  reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py,sha256=jIgOa888MYLLvVsn1ir3nbkhWLG5T6dBg7oDnp1q8BI,4108
249
+ reconcile/gql_definitions/aws_cloudwatch_log_retention/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
+ reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py,sha256=Am6y5LZIBncH9u7vwU48WRksnwGljpoS-xbP7MJA8-4,4976
249
251
  reconcile/gql_definitions/aws_saml_idp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
252
  reconcile/gql_definitions/aws_saml_idp/aws_accounts.py,sha256=pR9Qm6P9Roe4OJaDXvfm8AcfkSSAtriQdlwLwW7UdUU,2666
251
253
  reconcile/gql_definitions/aws_saml_roles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -293,7 +295,7 @@ reconcile/gql_definitions/common/pipeline_providers.py,sha256=9rpsqPuvj82B4ki56x
293
295
  reconcile/gql_definitions/common/quay_instances.py,sha256=toBkdYYVTmEafezAHZKgaW-mQ29xEW6jeronzsAlNyI,1786
294
296
  reconcile/gql_definitions/common/quay_orgs.py,sha256=NhA8kqvVUDbrsryEvEL5mlIv5R3T4XNhSRXtfL_yptY,1788
295
297
  reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
296
- reconcile/gql_definitions/common/saas_files.py,sha256=DA6aJspbuoSkVHlFI4HQ-YjdE5iN3eVg1k2lNtW0840,16863
298
+ reconcile/gql_definitions/common/saas_files.py,sha256=d1L_S5LgCMa4QuAqZGQYTWb5L_nPCOxSEjU4O__OeBU,17728
297
299
  reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=4VYP2VbwY8WVwtSFk2-jsUNhSmRD3X4FWKxetOKvmd0,2835
298
300
  reconcile/gql_definitions/common/saasherder_settings.py,sha256=nqQLcMwYxLseqq0BEcVvmrpIj2eQq0h8XDSpLN6GGCw,1793
299
301
  reconcile/gql_definitions/common/slack_workspaces.py,sha256=2o0kgi4QiaRuNmZJnc_By4F6NsKIdRaXkrufRQw7Nok,1753
@@ -305,7 +307,7 @@ reconcile/gql_definitions/cost_report/app_names.py,sha256=fzqYXyiTSll359J1F1o7qa
305
307
  reconcile/gql_definitions/cost_report/cost_namespaces.py,sha256=URRozAgSa9OnkqOCZf3MGH21_wcnsqYl0n-olXdjQH0,2286
306
308
  reconcile/gql_definitions/cost_report/settings.py,sha256=0nhBDJ5MZ1m7XkNDGrRLmsnUbzqZ4WRh_DDEEzKhcxU,2153
307
309
  reconcile/gql_definitions/dashdotdb_slo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
308
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py,sha256=MYYpVOc8Ze9w7k6-tlUkp5OaPG_5bqHPS5FhfWTw00U,4335
310
+ reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py,sha256=a1zLeL_NCbK25fOeT1gZOch8HNPFcHhzVXQty3jKT_s,2430
309
311
  reconcile/gql_definitions/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
310
312
  reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py,sha256=5gTuAnR2rnx2k6Rn7FMEAzw6GCZ6F5HZbqkmJ9-3NI4,2244
311
313
  reconcile/gql_definitions/dynatrace_token_provider/token_specs.py,sha256=XGsMuB8gowRpqJjkD_KRomx-1OswzyWbF4qjVdhionk,2555
@@ -333,6 +335,7 @@ reconcile/gql_definitions/fragments/aws_infra_management_account.py,sha256=uAmAL
333
335
  reconcile/gql_definitions/fragments/aws_vpc.py,sha256=T2egTwi2Rb0IRBBmsyag8xKpu_m6GbIAy80fhZNZwk8,1434
334
336
  reconcile/gql_definitions/fragments/aws_vpc_request.py,sha256=o0qUsPrFXs8GAbtgMXQmIJxc1mw5skSIzCcidE857g8,2460
335
337
  reconcile/gql_definitions/fragments/aws_vpc_request_subnet.py,sha256=qaTFT8cGzEslw51nUeb45Nfnv6kFxUm4CWrRR3xfBvA,760
338
+ reconcile/gql_definitions/fragments/container_image_mirror.py,sha256=qyfQlnKUCzFEPgUJ9VGmDYFmiGHR7VZ_YJNd4KeoolM,968
336
339
  reconcile/gql_definitions/fragments/deplopy_resources.py,sha256=0u3xYqL5NpMf149BJLfPhHqAOWu06aLULdNk_2Mulxg,1089
337
340
  reconcile/gql_definitions/fragments/disable.py,sha256=Ojw98OSxcovrtmw_aAyhaVHhIa1MSUbBfKX4i2IpI74,715
338
341
  reconcile/gql_definitions/fragments/email_service.py,sha256=0wKpICsg4pcMfr2lszvnqbuPX7wVYoJ5cYFU2uQkHbY,803
@@ -347,12 +350,16 @@ reconcile/gql_definitions/fragments/prometheus_instance.py,sha256=12ltnV9kdEw6Ln
347
350
  reconcile/gql_definitions/fragments/resource_limits_requirements.py,sha256=ucskQ_a8RxvFl5-IWxz5kk3g4-5Pvh_W4N3nLmuKxi0,744
348
351
  reconcile/gql_definitions/fragments/resource_requests_requirements.py,sha256=TFKO4YALFPanSvZvIJFz0dCioBU7i73Q6hkDtGMvs9I,736
349
352
  reconcile/gql_definitions/fragments/resource_values.py,sha256=-N2lNRhWp8PgocmIeX3U9f3l90Q97N2lXoq1pXdb_LE,742
353
+ reconcile/gql_definitions/fragments/saas_slo_document.py,sha256=6Ko_Kqny9gixPLKwr8RHL6DNx32rkNV24myurCVko-Q,2635
350
354
  reconcile/gql_definitions/fragments/saas_target_namespace.py,sha256=6f6WaerElaRi9_Ro-0CyWUkMHsbXlm0h9YXklftBwag,3991
351
355
  reconcile/gql_definitions/fragments/serviceaccount_token.py,sha256=2pG4rxAjvT-YsFBnm4zl301i7DCYznp99HOEGA-216I,1117
352
356
  reconcile/gql_definitions/fragments/terraform_state.py,sha256=S5QuTR9YlvUObiU7hevS9ybxZEssWoRGqCR9YtGwePs,1024
353
357
  reconcile/gql_definitions/fragments/upgrade_policy.py,sha256=cVza8zfra1E3yBsHiS-hKbys17fvv572GFnKshJjluE,1246
354
358
  reconcile/gql_definitions/fragments/user.py,sha256=TZyFEs1fBg5PkvWdyCxFDZ_3aRhcQzusfhObXFiOU_0,1025
355
359
  reconcile/gql_definitions/fragments/vault_secret.py,sha256=8xoQJNx1jKw_1yradq1iLEYWzuOHra1bEHHU7WHKxqo,833
360
+ reconcile/gql_definitions/gcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
361
+ reconcile/gql_definitions/gcp/gcp_docker_repos.py,sha256=HvNaJxQYNPBTDmk26cOUY5_C5oBfau4bdfuI-L1Vcps,3338
362
+ reconcile/gql_definitions/gcp/gcp_projects.py,sha256=7LslYFSN2r8vYhYdi4s-zOkIrqpqyt4ayxbPNMie9M4,2108
356
363
  reconcile/gql_definitions/gitlab_members/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
357
364
  reconcile/gql_definitions/gitlab_members/gitlab_instances.py,sha256=oYPvfiOsPTGHXQeSfxXvBuvJFrwp0VtE2F0lVKFQMoU,2206
358
365
  reconcile/gql_definitions/gitlab_members/permissions.py,sha256=Qzj3Fpv7xj8v9eygeP312nHRNg8er8XMRBveynPIyQM,3302
@@ -575,6 +582,7 @@ reconcile/typed_queries/vault.py,sha256=lkRsmobykorof3fcrIPLz-NgvAiSOWSOZc_jXBln
575
582
  reconcile/typed_queries/app_interface_metrics_exporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
576
583
  reconcile/typed_queries/app_interface_metrics_exporter/onboarding_status.py,sha256=X-N1WJGOL6OR9940P0_K4-YJzkL5Vg4favhYrBxXD9A,327
577
584
  reconcile/typed_queries/app_interface_metrics_exporter/terraform_repo.py,sha256=r-nJ5CucAOE_cwxnbVp5lmAAfHBG8t1h2tVmhviVYls,290
585
+ reconcile/typed_queries/aws_cloudwatch_log_retention/aws_accounts.py,sha256=WiQ84vEZp-oYvD4CVZaFDYcMBn-pkO3slwsHIQxvHks,296
578
586
  reconcile/typed_queries/cost_report/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
579
587
  reconcile/typed_queries/cost_report/app_names.py,sha256=HMEMIqAbMyVQfoQ5YXTXE4xDt7FaXBRz0QIHnsIZC1c,478
580
588
  reconcile/typed_queries/cost_report/cost_namespaces.py,sha256=1GUjWXQj7U2djVHBPYcd8Cy2-enKXf0-GaplLi8JZw4,1178
@@ -643,6 +651,7 @@ reconcile/utils/prometheus.py,sha256=Ad0rwLbxRuuYjHwkwJloHEdK0bvy42h-p-HIT1DhDhs
643
651
  reconcile/utils/promotion_state.py,sha256=McSgGj3oog83ThJCrMR2v8q6Xb_Pxij-HEe_RbDu8cg,3946
644
652
  reconcile/utils/promtool.py,sha256=xmPBWEApkk0L2qZBAvTxakNXxfTz-tVLPFxGnpsxXnM,2831
645
653
  reconcile/utils/quay_api.py,sha256=uE_jxcdy3ViHtYFAfwDQuFDaO7Pr6AAPoVnmORbyHio,7822
654
+ reconcile/utils/quay_mirror.py,sha256=dpWCNv5lITwIk6Q9RkmqaQKHNk_JPy27UQEribJ7E-U,1324
646
655
  reconcile/utils/raw_github_api.py,sha256=2WKtE8ABYYB9UGOAh9N_kLkksBWL3320Z2_scteZddI,2805
647
656
  reconcile/utils/repo_owners.py,sha256=BHrAXxKyvn4qWJwFPWYGTtfgnLmYnWtYFEJGFeD__FE,6573
648
657
  reconcile/utils/rest_api_base.py,sha256=MT7tp6CQO2S5aKfVOzw_hipWg7wAGoOqkm4qurI1hEU,4342
@@ -650,14 +659,15 @@ reconcile/utils/ruamel.py,sha256=FzL4_L0FnMOUZmgThrZSMJs5MTdXwiy-E9MZWfk8bh8,397
650
659
  reconcile/utils/secret_reader.py,sha256=MaP56KZaAE35EyYbgAitdm6fUSxdzWeGFSOym9qiZkw,10206
651
660
  reconcile/utils/semver_helper.py,sha256=-WfPOMSA2v1h7hT3PwVf-Htg7wOsoKlQC1JdmDX2Ars,1268
652
661
  reconcile/utils/sharding.py,sha256=DDBHfs5TT9UgjmzewiXUjbncnrPuceAZWeOA4veGa7s,843
653
- reconcile/utils/slack_api.py,sha256=iaOFzv3wiZRhcgYK2NB4lsG6ymNsGk2MEuj0PgZVp7w,17355
662
+ reconcile/utils/slack_api.py,sha256=CKHjO1EyNpJsqZYEnN5uRMVF-soTCYwUma_Th4enHSo,17507
663
+ reconcile/utils/slo_document_manager.py,sha256=CPgM2oH4AVzBqenakWo59R5yfwB62tnxSnSOHgir7l8,9500
654
664
  reconcile/utils/smtp_client.py,sha256=0xefB4I9E5eBB-FlxFJYjvz3Kvuqi_K3Ma_Wk0NAQKM,2779
655
665
  reconcile/utils/sqs_gateway.py,sha256=XNIf3PY4UCPNufP2Ul0UJj3fKlt5larBba-VTT-41Fg,2265
656
666
  reconcile/utils/state.py,sha256=az4tBmZ0EdbFcAGiBVUxs3cr2-BVWsuDQiNTvjjQq8s,16378
657
667
  reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
658
668
  reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
659
669
  reconcile/utils/terraform_client.py,sha256=IDlrNvGEc2i6ElZIL_fzaJEad1nRC3DkP9_VXhJXmU0,37329
660
- reconcile/utils/terrascript_aws_client.py,sha256=-knIxxuez_gmaI4OvkMq3YeYdZgzkDIVVorFdS_nw4E,289989
670
+ reconcile/utils/terrascript_aws_client.py,sha256=qQAwDAUK131tm2oBWBJzlKFYtpv7mPkqW1u19-A3wds,292248
661
671
  reconcile/utils/three_way_diff_strategy.py,sha256=oQcHXd9LVhirJfoaOBoHUYuZVGfyL2voKr6KVI34zZE,4833
662
672
  reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
663
673
  reconcile/utils/vault.py,sha256=aSA8l9cJlPUHpChFGl27nSY-Mpq9FMjBo7Dcgb1BVfM,15036
@@ -684,7 +694,7 @@ reconcile/utils/clusterhealth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
684
694
  reconcile/utils/clusterhealth/providerbase.py,sha256=DXomGYogckBLqWtXn0PXU0hWYxB6K0F7ernldrkHhVY,1140
685
695
  reconcile/utils/clusterhealth/telemeter.py,sha256=PllSLsJXvGNatmTF4mxCNPVbDrpr_MPk0m5pWj-LT6g,1534
686
696
  reconcile/utils/dynatrace/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
687
- reconcile/utils/dynatrace/client.py,sha256=RUk6KH-3CJyfJ1jolrdGQR4Hhz-tIWWJo9dsZ1IgJVw,3736
697
+ reconcile/utils/dynatrace/client.py,sha256=H8EjqmZlB1a2ionAjV8_R1ozs9lWbmPCYKLe0J8kZAs,2838
688
698
  reconcile/utils/glitchtip/__init__.py,sha256=FT6iBhGqoe7KExFdbgL8AYUb64iW_4snF5__Dcl7yt0,258
689
699
  reconcile/utils/glitchtip/client.py,sha256=F_x18QMHfeNoS3vS_VvjVm1IKnwGOsXvopjR9iwj4aY,8948
690
700
  reconcile/utils/glitchtip/models.py,sha256=FyNt9EA9IS6tlsvqz-j7SkL9MoT_zIUTun0EiC9No6U,6684
@@ -749,9 +759,9 @@ reconcile/utils/runtime/meta.py,sha256=dWdKS9eHVuowFkTK4lgXJ723vS1y9giOMzePUKnHn
749
759
  reconcile/utils/runtime/runner.py,sha256=I30KRrX1UQbHc_Ir1cIZX3OfNSdoHKdnDSPAEB69Ilk,7944
750
760
  reconcile/utils/runtime/sharding.py,sha256=r0ieUtNed7NvknSw6qQrCkKpVXE1shuHGnfFcnpA_k4,16142
751
761
  reconcile/utils/saasherder/__init__.py,sha256=3U8plqMAPRE1kjwZ5YnIsYsggTf4_gS7flRUEuXVBAs,343
752
- reconcile/utils/saasherder/interfaces.py,sha256=2Fjc34Us5q166P6bWVmSEBeYNTnWAPrI9EHwYUnEeuw,9098
762
+ reconcile/utils/saasherder/interfaces.py,sha256=NEYQspYfyWQhBeJyNCqSFbixi1A4wRVGB7FeNM5BDCk,9141
753
763
  reconcile/utils/saasherder/models.py,sha256=JaOz_DEtudJZhiDe90kaBlJkppFufn81V92oK9PHYx0,10208
754
- reconcile/utils/saasherder/saasherder.py,sha256=13LeAw12QR7wg4eU92iDsNXTCSCBrBp6LKvACn8ndp0,86834
764
+ reconcile/utils/saasherder/saasherder.py,sha256=ZeYwUSrWbJ0XkmQv92dUGPrhxd5zBKnDEM7_uzRroFE,87067
755
765
  reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
756
766
  reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
757
767
  reconcile/utils/terraform/config_client.py,sha256=gRL1rQ0AqvShei_rcGqC3HDYGskOFKE1nPrJyJE9yno,4676
@@ -764,18 +774,18 @@ reconcile/utils/unleash/__init__.py,sha256=2PsN3GlLU8DOyWSvv5q9uzwuFn_vYtfEo-mmV
764
774
  reconcile/utils/unleash/client.py,sha256=YrJnauxjcy1ml7W2AHg7dzIH_fVK_GugoRu7IFmk6e0,3505
765
775
  reconcile/utils/unleash/server.py,sha256=907gDh9Ee8UxLqusnfpzE-7LUnttB38D4xhVJ0vMf_M,4439
766
776
  tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
777
+ tools/alert_report.py,sha256=PqhFD2Yy_-dYCCSdNjoXbU6-FxbKnxCLLbcgjWmePhE,5051
767
778
  tools/app_interface_metrics_exporter.py,sha256=f1qwTmQfEcs98uBVRyBa0k7GQXdiSwd7w1hDVjhdGcQ,2303
768
779
  tools/app_interface_reporter.py,sha256=0_oq1-mL0UOh1x5G8CoKaEVJqK-XTKE7PX7IbRTovBc,17224
769
780
  tools/app_sre_tekton_access_reporter.py,sha256=o9prLUgQpwO3msRWc2as1xT1y9OB3znkpgvLr0Ys8_M,3146
770
781
  tools/app_sre_tekton_access_revalidation.py,sha256=66nHEaY-bIqxIhpcmwN8AvQZu6ZXenfkg4Fut0pVZRM,2726
771
782
  tools/glitchtip_access_reporter.py,sha256=o01A6b88t3Wie6tj_tJWWVo2J01LxQ_a9giGm4UzEaU,2901
772
783
  tools/glitchtip_access_revalidation.py,sha256=PXN5wxl6OX8sxddPaakDF3X79nFLvpm-lz0mWLVelw0,2806
773
- tools/qontract_cli.py,sha256=VmwXfvYEUewhvTYA3M2ucjRzhCb2G42AWrb9asMsdSQ,157451
774
- tools/sd_app_sre_alert_report.py,sha256=jQpJdXVID68bSNtJNOGDh0-ei1CfEUS4Itr4MAaBNFA,5062
784
+ tools/qontract_cli.py,sha256=pSN7UAWiI4lpOe_UHPWTBNG9adDLsJ5ZtcaIap0ChYg,157687
775
785
  tools/template_validation.py,sha256=qpKYaTgk0GOPGa2Ct5_5sKdwIHtCAKIBGzsMPuJU5fw,3371
776
786
  tools/cli_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
777
787
  tools/cli_commands/container_images_report.py,sha256=SXh6sZ1dXXzd-2R5eeBufCtW3J4-Y55--0MZLdo4lr8,5409
778
- tools/cli_commands/erv2.py,sha256=5EekfLBoA0spsdUHrPH47_x7bxxe_q7dTWW7nDw3UxM,23833
788
+ tools/cli_commands/erv2.py,sha256=WJgom7Fe2HuM31QKieYs_3evJuH7DEyd53sV-FKX7PU,26047
779
789
  tools/cli_commands/gpg_encrypt.py,sha256=JWwds_Qg7KhSJMIGUh8TfI5-Jf17iUtmaEi4kWJxfVE,4907
780
790
  tools/cli_commands/systems_and_tools.py,sha256=EMHOF1AtUDaoSk0bbjl6oUKYAz4rTZjIBaF-6E6GspM,16816
781
791
  tools/cli_commands/cost_report/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -797,7 +807,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
797
807
  tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
798
808
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
799
809
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
800
- qontract_reconcile-0.10.2.dev159.dist-info/METADATA,sha256=xiCIKDXtULyvmvHhV2FclCguppmcLFNhWWsIwmKbsyU,24627
801
- qontract_reconcile-0.10.2.dev159.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
802
- qontract_reconcile-0.10.2.dev159.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
803
- qontract_reconcile-0.10.2.dev159.dist-info/RECORD,,
810
+ qontract_reconcile-0.10.2.dev173.dist-info/METADATA,sha256=FvNTPyg42RM_QQGG_jcF9gdrkgv1nVHkoGb1SuFL6nE,24627
811
+ qontract_reconcile-0.10.2.dev173.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
812
+ qontract_reconcile-0.10.2.dev173.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
813
+ qontract_reconcile-0.10.2.dev173.dist-info/RECORD,,
reconcile/acs_rbac.py CHANGED
@@ -29,6 +29,7 @@ PERMISSION_SET_NAMES = {
29
29
  "admin": "Admin",
30
30
  "analyst": "Analyst",
31
31
  "vuln-admin": "Vulnerability Management Admin",
32
+ "vuln-report-creator": "Vulnerability Report Creator",
32
33
  }
33
34
 
34
35
 
@@ -5,13 +5,22 @@ from collections import defaultdict
5
5
  from collections.abc import Iterable
6
6
  from datetime import UTC, datetime, timedelta
7
7
  from enum import Enum
8
- from typing import TYPE_CHECKING
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ )
9
11
 
10
12
  from botocore.exceptions import ClientError
11
13
  from pydantic import BaseModel
12
14
 
13
15
  from reconcile import queries
14
- from reconcile.queries import get_aws_accounts
16
+ from reconcile.gql_definitions.aws_cloudwatch_log_retention.aws_accounts import (
17
+ AWSAccountCleanupOptionCloudWatchV1,
18
+ AWSAccountV1,
19
+ )
20
+ from reconcile.typed_queries.aws_cloudwatch_log_retention.aws_accounts import (
21
+ get_aws_accounts,
22
+ )
23
+ from reconcile.utils import gql
15
24
  from reconcile.utils.aws_api import AWSApi
16
25
 
17
26
  if TYPE_CHECKING:
@@ -39,31 +48,33 @@ DEFAULT_AWS_CLOUDWATCH_CLEANUP_OPTION = AWSCloudwatchCleanupOption(
39
48
 
40
49
 
41
50
  def get_desired_cleanup_options_by_region(
42
- account: dict,
51
+ account: AWSAccountV1,
43
52
  ) -> dict[str, list[AWSCloudwatchCleanupOption]]:
44
- default_region = account["resourcesDefaultRegion"]
53
+ default_region = account.resources_default_region
45
54
  result = defaultdict(list)
46
- if cleanup := account.get("cleanup"):
47
- for cleanup_option in cleanup:
48
- if cleanup_option["provider"] == "cloudwatch":
49
- region = cleanup_option.get("region") or default_region
50
- result[region].append(
51
- AWSCloudwatchCleanupOption(
52
- regex=re.compile(cleanup_option["regex"]),
53
- retention_in_days=cleanup_option["retention_in_days"],
54
- delete_empty_log_group=bool(
55
- cleanup_option["delete_empty_log_group"]
56
- ),
57
- )
55
+ for cleanup_option in account.cleanup or []:
56
+ if isinstance(cleanup_option, AWSAccountCleanupOptionCloudWatchV1):
57
+ region = cleanup_option.region or default_region
58
+ result[region].append(
59
+ AWSCloudwatchCleanupOption(
60
+ regex=re.compile(cleanup_option.regex),
61
+ retention_in_days=cleanup_option.retention_in_days,
62
+ delete_empty_log_group=bool(cleanup_option.delete_empty_log_group),
58
63
  )
64
+ )
59
65
  if not result:
60
66
  result[default_region].append(DEFAULT_AWS_CLOUDWATCH_CLEANUP_OPTION)
61
67
  return result
62
68
 
63
69
 
64
- def create_awsapi_client(accounts: list, thread_pool_size: int) -> AWSApi:
70
+ def create_awsapi_client(accounts: list[AWSAccountV1], thread_pool_size: int) -> AWSApi:
65
71
  settings = queries.get_secret_reader_settings()
66
- return AWSApi(thread_pool_size, accounts, settings=settings, init_users=False)
72
+ return AWSApi(
73
+ thread_pool_size,
74
+ [account.dict(by_alias=True) for account in accounts],
75
+ settings=settings,
76
+ init_users=False,
77
+ )
67
78
 
68
79
 
69
80
  def is_empty(log_group: LogGroupTypeDef) -> bool:
@@ -192,10 +203,10 @@ def _find_desired_cleanup_option(
192
203
 
193
204
  def _reconcile_log_groups(
194
205
  dry_run: bool,
195
- aws_account: dict,
206
+ aws_account: AWSAccountV1,
196
207
  awsapi: AWSApi,
197
208
  ) -> None:
198
- account_name = aws_account["name"]
209
+ account_name = aws_account.name
199
210
  desired_cleanup_options_by_region = get_desired_cleanup_options_by_region(
200
211
  aws_account
201
212
  )
@@ -230,12 +241,15 @@ def _reconcile_log_groups(
230
241
  )
231
242
 
232
243
 
233
- def get_active_aws_accounts() -> list[dict]:
244
+ def get_active_aws_accounts() -> list[AWSAccountV1]:
234
245
  return [
235
- a
236
- for a in get_aws_accounts(cleanup=True)
237
- if "aws-cloudwatch-log-retention"
238
- not in (a.get("disable") or {}).get("integrations", [])
246
+ account
247
+ for account in get_aws_accounts(gql.get_api())
248
+ if not (
249
+ account.disable
250
+ and account.disable.integrations
251
+ and "aws-cloudwatch-log-retention" in account.disable.integrations
252
+ )
239
253
  ]
240
254
 
241
255
 
reconcile/cli.py CHANGED
@@ -1849,15 +1849,13 @@ def quay_membership(ctx):
1849
1849
  run_integration(reconcile.quay_membership, ctx.obj)
1850
1850
 
1851
1851
 
1852
- @integration.command(
1853
- short_help="Mirrors external images into Google Container Registry."
1854
- )
1852
+ @integration.command(short_help="Mirrors external images into GCP Artifact Registry.")
1855
1853
  @click.pass_context
1856
1854
  @binary(["skopeo"])
1857
- def gcr_mirror(ctx):
1858
- import reconcile.gcr_mirror
1855
+ def gcp_image_mirror(ctx):
1856
+ import reconcile.gcp_image_mirror
1859
1857
 
1860
- run_integration(reconcile.gcr_mirror, ctx.obj)
1858
+ run_integration(reconcile.gcp_image_mirror, ctx.obj)
1861
1859
 
1862
1860
 
1863
1861
  @integration.command(short_help="Mirrors external images into Quay.")
@@ -1,11 +1,6 @@
1
- from collections.abc import Iterable
2
- from dataclasses import dataclass
3
- from math import isnan
4
1
  from typing import Any
5
2
 
6
- import jinja2
7
3
  import requests
8
- from requests import Response
9
4
  from sretoolbox.utils import threaded
10
5
 
11
6
  from reconcile.dashdotdb_base import (
@@ -13,9 +8,9 @@ from reconcile.dashdotdb_base import (
13
8
  DashdotdbBase,
14
9
  )
15
10
  from reconcile.gql_definitions.dashdotdb_slo.slo_documents_query import (
16
- SLODocumentV1,
17
11
  query,
18
12
  )
13
+ from reconcile.gql_definitions.fragments.saas_slo_document import SLODocument
19
14
  from reconcile.typed_queries.app_interface_vault_settings import (
20
15
  get_app_interface_vault_settings,
21
16
  )
@@ -24,40 +19,22 @@ from reconcile.utils.secret_reader import (
24
19
  SecretReaderBase,
25
20
  create_secret_reader,
26
21
  )
22
+ from reconcile.utils.slo_document_manager import (
23
+ SLODetails,
24
+ SLODocumentManager,
25
+ )
27
26
 
28
27
  QONTRACT_INTEGRATION = "dashdotdb-slo"
28
+ READ_TIMEOUT = 300
29
+ MAX_RETRIES = 2
29
30
 
30
31
 
31
- def get_slo_documents() -> list[SLODocumentV1]:
32
+ def get_slo_documents() -> list[SLODocument]:
32
33
  gqlapi = gql.get_api()
33
34
  data = query(gqlapi.query)
34
35
  return list(data.slo_documents or [])
35
36
 
36
37
 
37
- @dataclass
38
- class ServiceSLO:
39
- name: str
40
- sli_type: str
41
- slo_doc_name: str
42
- namespace_name: str
43
- cluster_name: str
44
- service_name: str
45
- value: float
46
- target: float
47
-
48
- def dashdot_payload(self) -> dict[str, Any]:
49
- return {
50
- "name": self.name,
51
- "SLIType": self.sli_type,
52
- "SLODoc": {"name": self.slo_doc_name},
53
- "namespace": {"name": self.namespace_name},
54
- "cluster": {"name": self.cluster_name},
55
- "service": {"name": self.service_name},
56
- "value": self.value,
57
- "target": self.target,
58
- }
59
-
60
-
61
38
  class DashdotdbSLO(DashdotdbBase):
62
39
  def __init__(
63
40
  self, dry_run: bool, thread_pool_size: int, secret_reader: SecretReaderBase
@@ -70,19 +47,28 @@ class DashdotdbSLO(DashdotdbBase):
70
47
  secret_reader=secret_reader,
71
48
  )
72
49
 
73
- def _post(self, service_slos: Iterable[ServiceSLO]) -> Response | None:
74
- for item in service_slos:
75
- LOG.debug(f"About to POST SLO JSON item to dashdotDB:\n{item}\n")
76
-
77
- response = None
78
-
79
- for item in service_slos:
80
- slo_name = item.name
81
- endpoint = f"{self.dashdotdb_url}/api/v1/serviceslometrics/{slo_name}"
82
- payload = item.dashdot_payload()
83
- if self.dry_run:
84
- continue
50
+ @staticmethod
51
+ def get_dash_dot_db_payload(slo: SLODetails) -> dict[str, Any]:
52
+ return {
53
+ "name": slo.slo.name,
54
+ "SLIType": slo.slo.sli_type,
55
+ "SLODoc": {"name": slo.slo_document_name},
56
+ "namespace": {"name": slo.namespace_name},
57
+ "cluster": {"name": slo.cluster_name},
58
+ "service": {"name": slo.service_name},
59
+ "value": slo.current_slo_value,
60
+ "target": slo.slo.slo_target,
61
+ }
85
62
 
63
+ def _post(self, service_slo: SLODetails) -> None:
64
+ LOG.debug(f"About to POST SLO JSON item to dashdotDB:\n{service_slo}\n")
65
+ slo_name = service_slo.slo.name
66
+ endpoint = f"{self.dashdotdb_url}/api/v1/serviceslometrics/{slo_name}"
67
+ if service_slo.slo.slo_target_unit == "percent_0_1":
68
+ service_slo.current_slo_value *= 100
69
+ service_slo.slo.slo_target *= 100
70
+ payload = self.get_dash_dot_db_payload(service_slo)
71
+ if not self.dry_run:
86
72
  LOG.info("%s syncing slo %s", self.logmarker, slo_name)
87
73
  try:
88
74
  response = self._do_post(endpoint, payload)
@@ -94,127 +80,30 @@ class DashdotdbSLO(DashdotdbBase):
94
80
  LOG.error("%s error posting %s - %s", self.logmarker, slo_name, details)
95
81
 
96
82
  LOG.info("%s slo %s synced", self.logmarker, slo_name)
97
- return response
98
-
99
- def _get_service_slo(self, slo_document: SLODocumentV1) -> list[ServiceSLO]:
100
- LOG.debug("SLO: processing %s", slo_document.name)
101
- result: list[ServiceSLO] = []
102
- for namespace_access in slo_document.namespaces:
103
- if (
104
- namespace_access.slo_namespace
105
- and namespace_access.prometheus_access is None
106
- ):
107
- continue
108
-
109
- ns = namespace_access.namespace
110
- promtoken: str | None = None
111
- username: str | None = None
112
- password: str | None = None
113
- if namespace_access.prometheus_access:
114
- promurl = namespace_access.prometheus_access.url
115
- if (
116
- namespace_access.prometheus_access.username
117
- and namespace_access.prometheus_access.password
118
- ):
119
- username = self.secret_reader.read_secret(
120
- namespace_access.prometheus_access.username
121
- )
122
- password = self.secret_reader.read_secret(
123
- namespace_access.prometheus_access.password
124
- )
125
- else:
126
- promurl = ns.cluster.prometheus_url
127
- if not ns.cluster.automation_token:
128
- LOG.error(
129
- "namespace does not have automation token set %s - skipping", ns
130
- )
131
- continue
132
- promtoken = self._get_automation_token(ns.cluster.automation_token)
133
- for slo in slo_document.slos or []:
134
- unit = slo.slo_target_unit
135
- expr = slo.expr
136
- template = jinja2.Template(expr)
137
- window = slo.slo_parameters.window
138
- promquery = template.render({"window": window})
139
-
140
- try:
141
- prom_response = self._promget(
142
- url=promurl,
143
- params={"query": (f"{promquery}")},
144
- token=promtoken,
145
- username=username,
146
- password=password,
147
- )
148
- except requests.exceptions.ConnectionError as error:
149
- # This can happen when prometheus is unreachable, or when running locally
150
- # and some prometheus URL are openshift service names. The trick is to run
151
- # with `oc port-forward` and update the local hosts file if we need to query those.
152
- LOG.error(
153
- f"{self.logmarker} Could not reach prometheus at {promurl}: {error}."
154
- f"Skipping SLOs from SLO doc {slo_document.name}"
155
- )
156
- # cannot connect to this prometheus, skip all
157
- raise
158
- except requests.exceptions.HTTPError as error:
159
- LOG.error(
160
- f"{self.logmarker} Error wile querying {promurl}: {error}."
161
- f"Skipping SLO '{slo.name} from SLO doc {slo_document.name}"
162
- )
163
- # it could be a query issue, keep processing other SLOs from this doc
164
- continue
165
-
166
- prom_result = prom_response["data"]["result"]
167
- if not prom_result:
168
- continue
169
-
170
- slo_value = prom_result[0]["value"]
171
- if not slo_value:
172
- continue
173
-
174
- slo_value = float(slo_value[1])
175
- if isnan(slo_value):
176
- LOG.warning(
177
- f"{self.logmarker} Skipping SLO '{slo.name}' in SLO doc '{slo_document.name}'"
178
- "as the obtained value is not a number (maybe a division by 0?)"
179
- )
180
- continue
181
- slo_target = float(slo.slo_target)
182
-
183
- # In Dash.DB we want to always store SLOs in percentages
184
- if unit == "percent_0_1":
185
- slo_value *= 100
186
- slo_target *= 100
187
-
188
- result.append(
189
- ServiceSLO(
190
- name=slo.name,
191
- sli_type=slo.sli_type,
192
- namespace_name=ns.name,
193
- cluster_name=ns.cluster.name,
194
- service_name=ns.app.name,
195
- value=slo_value,
196
- target=slo_target,
197
- slo_doc_name=slo_document.name,
198
- )
199
- )
200
- return result
201
83
 
202
84
  def run(self) -> None:
203
85
  slo_documents = get_slo_documents()
204
86
 
205
- service_slos: list[list[ServiceSLO]] = threaded.run(
206
- func=self._get_service_slo,
207
- iterable=slo_documents,
87
+ slo_document_manager = SLODocumentManager(
88
+ slo_documents=slo_documents,
89
+ secret_reader=self.secret_reader,
208
90
  thread_pool_size=self.thread_pool_size,
91
+ read_timeout=READ_TIMEOUT,
92
+ max_retries=MAX_RETRIES,
209
93
  )
210
94
 
95
+ slo_details_list = slo_document_manager.get_current_slo_list()
96
+ valid_slo_list = [slo for slo in slo_details_list if slo]
97
+
211
98
  self._get_token()
212
- threaded.run(
213
- func=self._post,
214
- iterable=service_slos,
215
- thread_pool_size=self.thread_pool_size,
216
- )
217
- self._close_token()
99
+ try:
100
+ threaded.run(
101
+ func=self._post,
102
+ iterable=valid_slo_list,
103
+ thread_pool_size=self.thread_pool_size,
104
+ )
105
+ finally:
106
+ self._close_token()
218
107
 
219
108
 
220
109
  def run(dry_run: bool = False, thread_pool_size: int = 10) -> None: