qontract-reconcile 0.10.2.dev135__py3-none-any.whl → 0.10.2.dev136__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.dev135.dist-info → qontract_reconcile-0.10.2.dev136.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev135.dist-info → qontract_reconcile-0.10.2.dev136.dist-info}/RECORD +35 -29
- reconcile/aws_ami_share.py +4 -2
- reconcile/aws_ecr_image_pull_secrets.py +15 -7
- reconcile/aws_garbage_collector.py +1 -1
- reconcile/aws_iam_keys.py +24 -17
- reconcile/aws_iam_password_reset.py +4 -2
- reconcile/aws_support_cases_sos.py +19 -6
- reconcile/closedbox_endpoint_monitoring_base.py +4 -3
- reconcile/cna/client.py +3 -3
- reconcile/cna/integration.py +4 -5
- reconcile/cna/state.py +3 -3
- reconcile/email_sender.py +65 -56
- reconcile/gcr_mirror.py +11 -9
- reconcile/github_org.py +57 -52
- reconcile/github_owners.py +8 -5
- reconcile/github_repo_invites.py +1 -1
- reconcile/github_repo_permissions_validator.py +3 -3
- reconcile/github_users.py +16 -12
- reconcile/github_validator.py +1 -1
- reconcile/gitlab_fork_compliance.py +9 -8
- reconcile/gitlab_labeler.py +1 -1
- reconcile/gitlab_mr_sqs_consumer.py +6 -3
- reconcile/gitlab_owners.py +29 -12
- reconcile/gql_definitions/email_sender/__init__.py +0 -0
- reconcile/gql_definitions/email_sender/apps.py +64 -0
- reconcile/gql_definitions/email_sender/emails.py +133 -0
- reconcile/gql_definitions/email_sender/users.py +62 -0
- reconcile/gql_definitions/fragments/email_service.py +32 -0
- reconcile/gql_definitions/fragments/email_user.py +28 -0
- reconcile/queries.py +0 -44
- reconcile/utils/jinja2/utils.py +4 -2
- reconcile/utils/smtp_client.py +1 -1
- {qontract_reconcile-0.10.2.dev135.dist-info → qontract_reconcile-0.10.2.dev136.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev135.dist-info → qontract_reconcile-0.10.2.dev136.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev135.dist-info → qontract_reconcile-0.10.2.dev136.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.dev136
|
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.dev135.dist-info → qontract_reconcile-0.10.2.dev136.dist-info}/RECORD
RENAMED
@@ -2,16 +2,16 @@ 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
4
|
reconcile/acs_rbac.py,sha256=hOQNOzD9f2Nioxb9XlspqnpZXH1DurCTnMcJpgyeB4E,22598
|
5
|
-
reconcile/aws_ami_share.py,sha256=
|
6
|
-
reconcile/aws_ecr_image_pull_secrets.py,sha256=
|
7
|
-
reconcile/aws_garbage_collector.py,sha256=
|
8
|
-
reconcile/aws_iam_keys.py,sha256=
|
9
|
-
reconcile/aws_iam_password_reset.py,sha256=
|
10
|
-
reconcile/aws_support_cases_sos.py,sha256=
|
5
|
+
reconcile/aws_ami_share.py,sha256=M_gT7y3cSAyT_Pm90PBCNDSmbZtqREqe2jNETh0i9Qs,3808
|
6
|
+
reconcile/aws_ecr_image_pull_secrets.py,sha256=F58PtX1GlB9XHqj8hGy9ItiTznXLAAKTNlWD9iT2MWI,2593
|
7
|
+
reconcile/aws_garbage_collector.py,sha256=PG_0qccQIW347WhdLAhfT9x0P9Mq_ojacvSy5vbJWj8,471
|
8
|
+
reconcile/aws_iam_keys.py,sha256=mw_lvmWqpJkzYW8Za6lHfxEMkT-_DOzWiCPhJAmYPIQ,3987
|
9
|
+
reconcile/aws_iam_password_reset.py,sha256=O0JX2N5kNRKs3u2xzu4NNrI6p0ag5JWy3MTsvZmtleg,3173
|
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
13
|
reconcile/cli.py,sha256=hwqPcZVmazrhzq1esPBk5jNHSzpfr7o9EmuuMqiPxfg,108430
|
14
|
-
reconcile/closedbox_endpoint_monitoring_base.py,sha256=
|
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
|
@@ -20,21 +20,21 @@ reconcile/dashdotdb_dvo.py,sha256=lCkZ0iby6HrNQb-3kYb6xrt8wCjVUZYxKzz9SiStfHU,89
|
|
20
20
|
reconcile/dashdotdb_slo.py,sha256=PU1GzT6Uy07IIO3Y62cFfRfaBJYUPrMkMp71Up80_bg,8334
|
21
21
|
reconcile/database_access_manager.py,sha256=Z3aAmw2LsmMIIor-bOGzziVZdVNC82Gmw8oHBUAFf-8,25577
|
22
22
|
reconcile/deadmanssnitch.py,sha256=n-5W-djUgwzpmdDM4eQIZpkkDmHY0vndt-42LJXI4Y8,7491
|
23
|
-
reconcile/email_sender.py,sha256=
|
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=
|
26
|
-
reconcile/github_org.py,sha256=
|
27
|
-
reconcile/github_owners.py,sha256=
|
28
|
-
reconcile/github_repo_invites.py,sha256=
|
29
|
-
reconcile/github_repo_permissions_validator.py,sha256=
|
30
|
-
reconcile/github_users.py,sha256=
|
31
|
-
reconcile/github_validator.py,sha256
|
32
|
-
reconcile/gitlab_fork_compliance.py,sha256=
|
25
|
+
reconcile/gcr_mirror.py,sha256=cdTd0CZU0qUsXJqe5k4dgpMQlyk__nyeGH0f_Cky3C0,8957
|
26
|
+
reconcile/github_org.py,sha256=Wc5cZamatuWsW2ZJT2ib5ps8l3iY3RXHwNUxVJerqz0,14173
|
27
|
+
reconcile/github_owners.py,sha256=viE1KJ-zaTxuZ5yItg2C263J0brn-Q-3hR_DkYDMbhY,3122
|
28
|
+
reconcile/github_repo_invites.py,sha256=U9UCzNVwrZ7MqODtFah8ogH0NNY-XjBin7G9gqHtCUY,2690
|
29
|
+
reconcile/github_repo_permissions_validator.py,sha256=DsM5IdEw3HvrpSRR9ZYjOLwE7QqD9cEhmFgM0QhHl5o,1784
|
30
|
+
reconcile/github_users.py,sha256=QdX164LZrm8sqggMj-0beCzWofpS6OEBfzKNrWPrfj0,3934
|
31
|
+
reconcile/github_validator.py,sha256=-j17tn3csFVjPMSPL3te48iWVkPZCncRXdeKeLdGjjQ,931
|
32
|
+
reconcile/gitlab_fork_compliance.py,sha256=RbHckzLnE9zkOFHJANzoejEMMbMAivmqJVs3Suvp9lU,4591
|
33
33
|
reconcile/gitlab_housekeeping.py,sha256=Gy1mhn33xGp9IyQFqs4VrBmhwJBD6x90XITDR_pU4MU,25416
|
34
|
-
reconcile/gitlab_labeler.py,sha256=
|
34
|
+
reconcile/gitlab_labeler.py,sha256=BA2dbXsN9hErUwJl22qcxfeH7XiPCuQ9LN3NddWdnpo,4540
|
35
35
|
reconcile/gitlab_members.py,sha256=MUIgYDLeJx2-_vMypyq2Pa17cpKdXATYhtVACS2ghpQ,8297
|
36
|
-
reconcile/gitlab_mr_sqs_consumer.py,sha256=
|
37
|
-
reconcile/gitlab_owners.py,sha256=
|
36
|
+
reconcile/gitlab_mr_sqs_consumer.py,sha256=i_MDVfA3Uk_TJiNkfEJzhO6_rwR7z3I3dH9oEw686U4,2681
|
37
|
+
reconcile/gitlab_owners.py,sha256=nIEsf3QWI3yIw_Bxy5oMaCmszTaNZDwQVaaZZxPgh4g,14447
|
38
38
|
reconcile/gitlab_permissions.py,sha256=gSGH6gAdJbPy5Z0rQGUqiNQSHty_tXQ_3Y4OQP_8nFs,8067
|
39
39
|
reconcile/gitlab_projects.py,sha256=K3tFf_aD1W4Ijp5q-9Qek3kwFGEWPcZ1kd7tzFJ4GyQ,1781
|
40
40
|
reconcile/integrations_manager.py,sha256=CY7cOj5dzt2se4IOg11VQvGQ-eTvLML5Q42Z9SSgeSk,9463
|
@@ -94,7 +94,7 @@ reconcile/quay_mirror.py,sha256=0KtQFwrvMNtlsPJ9F_-ICaVIjgIUjFxqipvAPcvyg3Q,1533
|
|
94
94
|
reconcile/quay_mirror_org.py,sha256=tXKuF6JtmaNRwu8_g_65U_Vpd6sFBYeXmJA-flVhylE,10764
|
95
95
|
reconcile/quay_permissions.py,sha256=9KOutS1w4RFQqkvMSy54VtsKNx56-phzP6yI_rEW-B8,4244
|
96
96
|
reconcile/quay_repos.py,sha256=cuEYG0HUe0ut5yvLdEwOF5-CmccpXQHRb_wDazvDrvQ,6895
|
97
|
-
reconcile/queries.py,sha256=
|
97
|
+
reconcile/queries.py,sha256=XU5ksCW6f8AmVHsg8WEAxiL4cwzLBkpvsYn9EqZ228Q,50890
|
98
98
|
reconcile/query_validator.py,sha256=MSh5pKLBksws4AqfuvT8nrIGucIbqX-IOzYyPYTLO7k,1491
|
99
99
|
reconcile/requests_sender.py,sha256=914iluuF4UVgG3VyxxtnHOu4yf6YKS2fIy6PViSsFTQ,3875
|
100
100
|
reconcile/resource_scraper.py,sha256=znXCHrU7YwPfKuxGBiUrV7T1tYtn4vlz9qmZlfy6Flg,2307
|
@@ -179,9 +179,9 @@ reconcile/change_owners/tester.py,sha256=ijDaSbFYT8fPinhjPrRlw_TCarTTJK5nUgzHSi1
|
|
179
179
|
reconcile/cluster_auth_rhidp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
180
180
|
reconcile/cluster_auth_rhidp/integration.py,sha256=KIAiP_XFjsOA2OE8oFJa8lD0T1a7EwOmhct2xbj7tr8,9560
|
181
181
|
reconcile/cna/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
182
|
-
reconcile/cna/client.py,sha256=
|
183
|
-
reconcile/cna/integration.py,sha256=
|
184
|
-
reconcile/cna/state.py,sha256=
|
182
|
+
reconcile/cna/client.py,sha256=32-G3fDZfVvkCN1vg0EbcsMNYBdJvXoXYI2ShFg6lbc,1586
|
183
|
+
reconcile/cna/integration.py,sha256=dybEWkSCl7V5OC7ZQYIN2j4QV2yWstIUEQy1GpYI2oI,5106
|
184
|
+
reconcile/cna/state.py,sha256=mJghfMGZZtyh8e6GwNNajI2AxEEJQ4e51tAgQ26zEuQ,4501
|
185
185
|
reconcile/cna/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
186
186
|
reconcile/cna/assets/asset.py,sha256=KWgA4fuDAEGsJwmR52WwK_YgSJMW-1cV2la3lmNf4iE,834
|
187
187
|
reconcile/cna/assets/asset_factory.py,sha256=7T7X_J6xIsoGETqBRI45_EyIKEdQcnRPt_GAuVuLQcc,785
|
@@ -309,6 +309,10 @@ reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py,sha256=MYYpVOc8Ze
|
|
309
309
|
reconcile/gql_definitions/dynatrace_token_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
310
310
|
reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py,sha256=5gTuAnR2rnx2k6Rn7FMEAzw6GCZ6F5HZbqkmJ9-3NI4,2244
|
311
311
|
reconcile/gql_definitions/dynatrace_token_provider/token_specs.py,sha256=XGsMuB8gowRpqJjkD_KRomx-1OswzyWbF4qjVdhionk,2555
|
312
|
+
reconcile/gql_definitions/email_sender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
313
|
+
reconcile/gql_definitions/email_sender/apps.py,sha256=prqXdFkeTQ31hF2E7e9sldr3F8iklGHsPAsTx3cOkeM,1715
|
314
|
+
reconcile/gql_definitions/email_sender/emails.py,sha256=JoEL_Urtepeho4VZGlHjrYOTImibtNtaj2va0zMaSFU,3454
|
315
|
+
reconcile/gql_definitions/email_sender/users.py,sha256=RAqJ3QqtR0ku_mumqQ4jZkP1hFqLExleJajEu5KVhIs,1670
|
312
316
|
reconcile/gql_definitions/endpoints_discovery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
313
317
|
reconcile/gql_definitions/endpoints_discovery/apps.py,sha256=aBWRAwDUJQ32ghJS4cPQcR9SNl20Fcwd3pxHDB3YJQY,3172
|
314
318
|
reconcile/gql_definitions/external_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -331,6 +335,8 @@ reconcile/gql_definitions/fragments/aws_vpc_request.py,sha256=o0qUsPrFXs8GAbtgMX
|
|
331
335
|
reconcile/gql_definitions/fragments/aws_vpc_request_subnet.py,sha256=qaTFT8cGzEslw51nUeb45Nfnv6kFxUm4CWrRR3xfBvA,760
|
332
336
|
reconcile/gql_definitions/fragments/deplopy_resources.py,sha256=0u3xYqL5NpMf149BJLfPhHqAOWu06aLULdNk_2Mulxg,1089
|
333
337
|
reconcile/gql_definitions/fragments/disable.py,sha256=Ojw98OSxcovrtmw_aAyhaVHhIa1MSUbBfKX4i2IpI74,715
|
338
|
+
reconcile/gql_definitions/fragments/email_service.py,sha256=0wKpICsg4pcMfr2lszvnqbuPX7wVYoJ5cYFU2uQkHbY,803
|
339
|
+
reconcile/gql_definitions/fragments/email_user.py,sha256=UOKbXXNH2Z_7ckgCeCMiBvbfs4qMMYs4PVqxSKNNmBQ,690
|
334
340
|
reconcile/gql_definitions/fragments/jumphost_common_fields.py,sha256=FOqqDRqzPdt4ZNTRRZPFYCKE1HIa1ATF0u0NsdZzyaw,1034
|
335
341
|
reconcile/gql_definitions/fragments/membership_source.py,sha256=rVjAIAhhAoH0_fUfltlFlGvYbvpRRAK4S6dH8OJ5hHE,1390
|
336
342
|
reconcile/gql_definitions/fragments/minimal_ocm_organization.py,sha256=G7uEwGR2qjtXl3yUUMWAzbihNKor0jj1_fcSd9qQOjw,731
|
@@ -645,7 +651,7 @@ reconcile/utils/secret_reader.py,sha256=MaP56KZaAE35EyYbgAitdm6fUSxdzWeGFSOym9qi
|
|
645
651
|
reconcile/utils/semver_helper.py,sha256=-WfPOMSA2v1h7hT3PwVf-Htg7wOsoKlQC1JdmDX2Ars,1268
|
646
652
|
reconcile/utils/sharding.py,sha256=DDBHfs5TT9UgjmzewiXUjbncnrPuceAZWeOA4veGa7s,843
|
647
653
|
reconcile/utils/slack_api.py,sha256=iaOFzv3wiZRhcgYK2NB4lsG6ymNsGk2MEuj0PgZVp7w,17355
|
648
|
-
reconcile/utils/smtp_client.py,sha256=
|
654
|
+
reconcile/utils/smtp_client.py,sha256=0xefB4I9E5eBB-FlxFJYjvz3Kvuqi_K3Ma_Wk0NAQKM,2779
|
649
655
|
reconcile/utils/sqs_gateway.py,sha256=XNIf3PY4UCPNufP2Ul0UJj3fKlt5larBba-VTT-41Fg,2265
|
650
656
|
reconcile/utils/state.py,sha256=az4tBmZ0EdbFcAGiBVUxs3cr2-BVWsuDQiNTvjjQq8s,16378
|
651
657
|
reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
|
@@ -688,7 +694,7 @@ reconcile/utils/internal_groups/models.py,sha256=y_IqBVqfGqNXiu0VudvBWFrm_-uafVm
|
|
688
694
|
reconcile/utils/jinja2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
689
695
|
reconcile/utils/jinja2/extensions.py,sha256=7K-uo6G2eCWa98MHT8fRPYIKCLQB_5D2keqQ_LyAfHM,1293
|
690
696
|
reconcile/utils/jinja2/filters.py,sha256=JfO_14APySBPidsMvHXG-8dULNPddZCE15Umjk_aSBk,4830
|
691
|
-
reconcile/utils/jinja2/utils.py,sha256=
|
697
|
+
reconcile/utils/jinja2/utils.py,sha256=AQYEhrA4eEl7-tjf8KyVheSGWS3n-56K7zoJIH9IMF4,8819
|
692
698
|
reconcile/utils/jobcontroller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
693
699
|
reconcile/utils/jobcontroller/controller.py,sha256=Vh08lZuCSIIceWGSDhBB00iFwTI9eeKZW1sfHlkAvSo,15373
|
694
700
|
reconcile/utils/jobcontroller/models.py,sha256=x9YIvWfYOOvXNKToFVx1H7qDrZb0Sa1KI_4Y0gl7rMM,6336
|
@@ -791,7 +797,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
791
797
|
tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
|
792
798
|
tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
|
793
799
|
tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
|
794
|
-
qontract_reconcile-0.10.2.
|
795
|
-
qontract_reconcile-0.10.2.
|
796
|
-
qontract_reconcile-0.10.2.
|
797
|
-
qontract_reconcile-0.10.2.
|
800
|
+
qontract_reconcile-0.10.2.dev136.dist-info/METADATA,sha256=UzAvn2oHDRdlTZTyBA6HDVAVsDtCEsw4ubf7GYLIiI0,24568
|
801
|
+
qontract_reconcile-0.10.2.dev136.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
802
|
+
qontract_reconcile-0.10.2.dev136.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
803
|
+
qontract_reconcile-0.10.2.dev136.dist-info/RECORD,,
|
reconcile/aws_ami_share.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
from collections.abc import (
|
3
|
+
Callable,
|
3
4
|
Iterable,
|
4
5
|
Mapping,
|
5
6
|
)
|
@@ -37,12 +38,13 @@ def get_region(
|
|
37
38
|
|
38
39
|
|
39
40
|
@defer
|
40
|
-
def run(dry_run, defer=None):
|
41
|
+
def run(dry_run: bool, defer: Callable | None = None) -> None:
|
41
42
|
accounts = queries.get_aws_accounts(sharing=True)
|
42
43
|
sharing_accounts = filter_accounts(accounts)
|
43
44
|
settings = queries.get_app_interface_settings()
|
44
45
|
aws_api = AWSApi(1, sharing_accounts, settings=settings, init_users=False)
|
45
|
-
defer
|
46
|
+
if defer:
|
47
|
+
defer(aws_api.cleanup)
|
46
48
|
|
47
49
|
for src_account in sharing_accounts:
|
48
50
|
sharing = src_account.get("sharing")
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import base64
|
2
2
|
import json
|
3
3
|
import logging
|
4
|
+
from collections.abc import Mapping
|
5
|
+
from typing import Any
|
4
6
|
|
5
7
|
from reconcile import queries
|
6
8
|
from reconcile.utils.aws_api import AWSApi
|
@@ -9,15 +11,15 @@ from reconcile.utils.vault import VaultClient
|
|
9
11
|
QONTRACT_INTEGRATION = "aws-ecr-image-pull-secrets"
|
10
12
|
|
11
13
|
|
12
|
-
def enc_dec(data):
|
14
|
+
def enc_dec(data: str) -> str:
|
13
15
|
return base64.b64encode(data.encode("utf-8")).decode("utf-8")
|
14
16
|
|
15
17
|
|
16
|
-
def get_password(token):
|
18
|
+
def get_password(token: str) -> str:
|
17
19
|
return base64.b64decode(token).decode("utf-8").split(":")[1]
|
18
20
|
|
19
21
|
|
20
|
-
def construct_dockercfg_secret_data(data):
|
22
|
+
def construct_dockercfg_secret_data(data: Mapping[str, Any]) -> dict[str, str]:
|
21
23
|
auth_data = data["authorizationData"][0]
|
22
24
|
server = auth_data["proxyEndpoint"]
|
23
25
|
token = auth_data["authorizationToken"]
|
@@ -36,7 +38,7 @@ def construct_dockercfg_secret_data(data):
|
|
36
38
|
return {".dockerconfigjson": enc_dec(json.dumps(data))}
|
37
39
|
|
38
40
|
|
39
|
-
def construct_basic_auth_secret_data(data):
|
41
|
+
def construct_basic_auth_secret_data(data: Mapping[str, Any]) -> dict[str, str]:
|
40
42
|
auth_data = data["authorizationData"][0]
|
41
43
|
token = auth_data["authorizationToken"]
|
42
44
|
password = get_password(token)
|
@@ -44,17 +46,23 @@ def construct_basic_auth_secret_data(data):
|
|
44
46
|
return {"user": enc_dec("AWS"), "token": enc_dec(password), "url": url}
|
45
47
|
|
46
48
|
|
47
|
-
def write_output_to_vault(
|
49
|
+
def write_output_to_vault(
|
50
|
+
dry_run: bool,
|
51
|
+
vault_path: str,
|
52
|
+
account: str,
|
53
|
+
secret_data: Mapping[str, str],
|
54
|
+
name: str,
|
55
|
+
) -> None:
|
48
56
|
integration_name = QONTRACT_INTEGRATION
|
49
57
|
secret_path = f"{vault_path}/{integration_name}/{account}/{name}"
|
50
58
|
secret = {"path": secret_path, "data": secret_data}
|
51
59
|
logging.info(["write_secret", secret_path])
|
52
60
|
vault_client = VaultClient()
|
53
61
|
if not dry_run:
|
54
|
-
vault_client.write(secret)
|
62
|
+
vault_client.write(secret) # type: ignore
|
55
63
|
|
56
64
|
|
57
|
-
def run(dry_run, vault_output_path=""):
|
65
|
+
def run(dry_run: bool, vault_output_path: str = "") -> None:
|
58
66
|
accounts = [a for a in queries.get_aws_accounts() if a.get("ecrs")]
|
59
67
|
settings = queries.get_app_interface_settings()
|
60
68
|
with AWSApi(1, accounts, settings=settings, init_ecr_auth_tokens=True) as aws:
|
@@ -4,7 +4,7 @@ from reconcile.utils.aws_api import AWSApi
|
|
4
4
|
QONTRACT_INTEGRATION = "aws-garbage-collector"
|
5
5
|
|
6
6
|
|
7
|
-
def run(dry_run, thread_pool_size=10):
|
7
|
+
def run(dry_run: bool, thread_pool_size: int = 10) -> None:
|
8
8
|
accounts = [a for a in queries.get_aws_accounts() if a.get("garbageCollection")]
|
9
9
|
settings = queries.get_app_interface_settings()
|
10
10
|
with AWSApi(thread_pool_size, accounts, settings=settings) as aws:
|
reconcile/aws_iam_keys.py
CHANGED
@@ -1,28 +1,28 @@
|
|
1
1
|
import logging
|
2
2
|
import shutil
|
3
3
|
import sys
|
4
|
+
from collections.abc import Callable, Iterable, Mapping
|
4
5
|
from typing import Any
|
5
6
|
|
6
7
|
from reconcile import queries
|
7
8
|
from reconcile.utils.aws_api import AWSApi
|
8
9
|
from reconcile.utils.defer import defer
|
9
|
-
from reconcile.utils.state import
|
10
|
-
State,
|
11
|
-
init_state,
|
12
|
-
)
|
10
|
+
from reconcile.utils.state import State, init_state
|
13
11
|
from reconcile.utils.terrascript_aws_client import TerrascriptClient as Terrascript
|
14
12
|
|
15
13
|
QONTRACT_INTEGRATION = "aws-iam-keys"
|
16
14
|
|
17
15
|
|
18
|
-
def filter_accounts(
|
16
|
+
def filter_accounts(
|
17
|
+
accounts: Iterable[dict[str, Any]], account_name: str | None
|
18
|
+
) -> list[dict[str, Any]]:
|
19
19
|
accounts = [a for a in accounts if a.get("deleteKeys")]
|
20
20
|
if account_name:
|
21
21
|
accounts = [a for a in accounts if a["name"] == account_name]
|
22
22
|
return accounts
|
23
23
|
|
24
24
|
|
25
|
-
def get_keys_to_delete(accounts) -> dict[str, list[str]]:
|
25
|
+
def get_keys_to_delete(accounts: Iterable[dict[str, Any]]) -> dict[str, list[str]]:
|
26
26
|
return {
|
27
27
|
account["name"]: account["deleteKeys"]
|
28
28
|
for account in accounts
|
@@ -37,13 +37,17 @@ def should_run(state: State, keys_to_delete: dict[str, list[str]]) -> bool:
|
|
37
37
|
return False
|
38
38
|
|
39
39
|
|
40
|
-
def update_state(state: State, keys_to_update: dict[str, list[str]]):
|
40
|
+
def update_state(state: State, keys_to_update: dict[str, list[str]]) -> None:
|
41
41
|
for account_name, keys in keys_to_update.items():
|
42
42
|
if state.get(account_name, []) != keys:
|
43
43
|
state.add(account_name, keys, force=True)
|
44
44
|
|
45
45
|
|
46
|
-
def init_tf_working_dirs(
|
46
|
+
def init_tf_working_dirs(
|
47
|
+
accounts: Iterable[dict[str, Any]],
|
48
|
+
thread_pool_size: int,
|
49
|
+
settings: Mapping[str, Any],
|
50
|
+
) -> dict[str, str]:
|
47
51
|
# copied here to avoid circular dependency
|
48
52
|
QONTRACT_INTEGRATION = "terraform_resources"
|
49
53
|
QONTRACT_TF_PREFIX = "qrtf"
|
@@ -64,19 +68,19 @@ def init_tf_working_dirs(accounts, thread_pool_size, settings):
|
|
64
68
|
return ts.dump()
|
65
69
|
|
66
70
|
|
67
|
-
def cleanup(working_dirs):
|
71
|
+
def cleanup(working_dirs: Mapping[str, str]) -> None:
|
68
72
|
for wd in working_dirs.values():
|
69
73
|
shutil.rmtree(wd)
|
70
74
|
|
71
75
|
|
72
76
|
@defer
|
73
77
|
def run(
|
74
|
-
dry_run,
|
75
|
-
thread_pool_size=10,
|
76
|
-
disable_service_account_keys=False,
|
77
|
-
account_name=None,
|
78
|
-
defer=None,
|
79
|
-
):
|
78
|
+
dry_run: bool,
|
79
|
+
thread_pool_size: int = 10,
|
80
|
+
disable_service_account_keys: bool = False,
|
81
|
+
account_name: str | None = None,
|
82
|
+
defer: Callable | None = None,
|
83
|
+
) -> None:
|
80
84
|
accounts = filter_accounts(
|
81
85
|
queries.get_aws_accounts(terraform_state=True), account_name
|
82
86
|
)
|
@@ -88,7 +92,8 @@ def run(
|
|
88
92
|
|
89
93
|
settings = queries.get_app_interface_settings()
|
90
94
|
state = init_state(integration=QONTRACT_INTEGRATION)
|
91
|
-
defer
|
95
|
+
if defer:
|
96
|
+
defer(state.cleanup)
|
92
97
|
keys_to_delete = get_keys_to_delete(accounts)
|
93
98
|
if not should_run(state, keys_to_delete):
|
94
99
|
logging.debug("nothing to do here")
|
@@ -97,7 +102,9 @@ def run(
|
|
97
102
|
return
|
98
103
|
|
99
104
|
working_dirs = init_tf_working_dirs(accounts, thread_pool_size, settings)
|
100
|
-
defer
|
105
|
+
if defer:
|
106
|
+
defer(lambda: cleanup(working_dirs))
|
107
|
+
|
101
108
|
with AWSApi(thread_pool_size, accounts, settings=settings) as aws:
|
102
109
|
error, service_account_recycle_complete = aws.delete_keys(
|
103
110
|
dry_run, keys_to_delete, working_dirs, disable_service_account_keys
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
3
|
from collections.abc import (
|
4
|
+
Callable,
|
4
5
|
Iterable,
|
5
6
|
Mapping,
|
6
7
|
)
|
@@ -44,12 +45,13 @@ class AwsAccountWithResets(BaseModel):
|
|
44
45
|
|
45
46
|
|
46
47
|
@defer
|
47
|
-
def run(dry_run, defer=None):
|
48
|
+
def run(dry_run: bool, defer: Callable | None = None) -> None:
|
48
49
|
accounts = queries.get_aws_accounts(reset_passwords=True)
|
49
50
|
settings = queries.get_app_interface_settings()
|
50
51
|
roles = queries.get_roles(aws=True, saas_files=False)
|
51
52
|
state = init_state(integration=QONTRACT_INTEGRATION)
|
52
|
-
defer
|
53
|
+
if defer:
|
54
|
+
defer(state.cleanup)
|
53
55
|
|
54
56
|
accounts_to_reset: list[AwsAccountWithResets] = []
|
55
57
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
import itertools
|
2
2
|
import logging
|
3
|
+
from collections.abc import Callable, Iterable, Mapping
|
4
|
+
from typing import Any
|
3
5
|
|
4
6
|
from reconcile import (
|
5
7
|
mr_client_gateway,
|
@@ -12,11 +14,11 @@ from reconcile.utils.mr import CreateDeleteAwsAccessKey
|
|
12
14
|
QONTRACT_INTEGRATION = "aws-support-cases-sos"
|
13
15
|
|
14
16
|
|
15
|
-
def filter_accounts(accounts):
|
17
|
+
def filter_accounts(accounts: Iterable[dict[str, Any]]) -> list[dict[str, Any]]:
|
16
18
|
return [a for a in accounts if a.get("premiumSupport")]
|
17
19
|
|
18
20
|
|
19
|
-
def get_deleted_keys(accounts):
|
21
|
+
def get_deleted_keys(accounts: Iterable[dict[str, Any]]) -> dict[str, list[str]]:
|
20
22
|
return {
|
21
23
|
account["name"]: account["deleteKeys"]
|
22
24
|
for account in accounts
|
@@ -24,7 +26,9 @@ def get_deleted_keys(accounts):
|
|
24
26
|
}
|
25
27
|
|
26
28
|
|
27
|
-
def get_keys_to_delete(
|
29
|
+
def get_keys_to_delete(
|
30
|
+
aws_support_cases: Mapping[str, Iterable[Mapping[str, Any]]],
|
31
|
+
) -> list[dict[str, str]]:
|
28
32
|
search_pattern = "We have become aware that the AWS Access Key "
|
29
33
|
keys = []
|
30
34
|
# ref:
|
@@ -43,10 +47,17 @@ def get_keys_to_delete(aws_support_cases):
|
|
43
47
|
|
44
48
|
|
45
49
|
@defer
|
46
|
-
def act(
|
50
|
+
def act(
|
51
|
+
dry_run: bool,
|
52
|
+
gitlab_project_id: str | None,
|
53
|
+
accounts: Iterable[dict[str, Any]],
|
54
|
+
keys_to_delete: list[dict[str, str]],
|
55
|
+
defer: Callable | None = None,
|
56
|
+
) -> None:
|
47
57
|
if not dry_run and keys_to_delete:
|
48
58
|
mr_cli = mr_client_gateway.init(gitlab_project_id=gitlab_project_id)
|
49
|
-
defer
|
59
|
+
if defer:
|
60
|
+
defer(mr_cli.cleanup)
|
50
61
|
|
51
62
|
for k in keys_to_delete:
|
52
63
|
account = k["account"]
|
@@ -59,7 +70,9 @@ def act(dry_run, gitlab_project_id, accounts, keys_to_delete, defer=None):
|
|
59
70
|
mr.submit(cli=mr_cli)
|
60
71
|
|
61
72
|
|
62
|
-
def run(
|
73
|
+
def run(
|
74
|
+
dry_run: bool, gitlab_project_id: str | None = None, thread_pool_size: int = 10
|
75
|
+
) -> None:
|
63
76
|
accounts = filter_accounts(queries.get_aws_accounts())
|
64
77
|
settings = queries.get_app_interface_settings()
|
65
78
|
deleted_keys = get_deleted_keys(accounts)
|
@@ -63,7 +63,7 @@ class EndpointMonitoringProvider:
|
|
63
63
|
return None
|
64
64
|
|
65
65
|
@property
|
66
|
-
def metric_labels(self):
|
66
|
+
def metric_labels(self) -> dict[str, Any]:
|
67
67
|
return json.loads(self.metricLabels) if self.metricLabels else {}
|
68
68
|
|
69
69
|
|
@@ -136,7 +136,7 @@ def run_for_provider(
|
|
136
136
|
thread_pool_size: int,
|
137
137
|
internal: bool,
|
138
138
|
use_jump_host: bool,
|
139
|
-
defer=None,
|
139
|
+
defer: Callable | None = None,
|
140
140
|
) -> None:
|
141
141
|
# prepare
|
142
142
|
desired_endpoints = get_endpoints(provider)
|
@@ -152,7 +152,8 @@ def run_for_provider(
|
|
152
152
|
integration_version=integration_version,
|
153
153
|
override_managed_types=["Probe"],
|
154
154
|
)
|
155
|
-
defer
|
155
|
+
if defer:
|
156
|
+
defer(oc_map.cleanup)
|
156
157
|
|
157
158
|
# reconcile
|
158
159
|
for ep_mon_provider, endpoints in desired_endpoints.items():
|
reconcile/cna/client.py
CHANGED
@@ -23,7 +23,7 @@ class CNAClient:
|
|
23
23
|
cnas = self._ocm_client.get(api_path="/api/cna-management/v1/cnas")
|
24
24
|
return cnas.get("items", [])
|
25
25
|
|
26
|
-
def create(self, asset: Asset, dry_run: bool = False):
|
26
|
+
def create(self, asset: Asset, dry_run: bool = False) -> None:
|
27
27
|
if dry_run:
|
28
28
|
logging.info("CREATE %s", asset)
|
29
29
|
return
|
@@ -32,7 +32,7 @@ class CNAClient:
|
|
32
32
|
data=asset.api_payload(),
|
33
33
|
)
|
34
34
|
|
35
|
-
def delete(self, asset: Asset, dry_run: bool = False):
|
35
|
+
def delete(self, asset: Asset, dry_run: bool = False) -> None:
|
36
36
|
if dry_run:
|
37
37
|
logging.info("DELETE %s", asset)
|
38
38
|
return
|
@@ -41,7 +41,7 @@ class CNAClient:
|
|
41
41
|
api_path=asset.href,
|
42
42
|
)
|
43
43
|
|
44
|
-
def update(self, asset: Asset, dry_run: bool = False):
|
44
|
+
def update(self, asset: Asset, dry_run: bool = False) -> None:
|
45
45
|
if dry_run:
|
46
46
|
logging.info("UPDATE %s", asset)
|
47
47
|
return
|
reconcile/cna/integration.py
CHANGED
@@ -46,13 +46,13 @@ class CNAIntegration:
|
|
46
46
|
namespaces: Iterable[NamespaceV1],
|
47
47
|
desired_states: Mapping[str, State] | None = None,
|
48
48
|
current_states: Mapping[str, State] | None = None,
|
49
|
-
):
|
49
|
+
) -> None:
|
50
50
|
self._cna_clients = cna_clients
|
51
51
|
self._namespaces = namespaces
|
52
52
|
self._desired_states = desired_states or defaultdict(State)
|
53
53
|
self._current_states = current_states or defaultdict(State)
|
54
54
|
|
55
|
-
def assemble_desired_states(self):
|
55
|
+
def assemble_desired_states(self) -> None:
|
56
56
|
self._desired_states = defaultdict(State)
|
57
57
|
for namespace in self._namespaces:
|
58
58
|
for provider in namespace.external_resources or []:
|
@@ -64,7 +64,7 @@ class CNAIntegration:
|
|
64
64
|
asset_factory_from_schema(resource)
|
65
65
|
)
|
66
66
|
|
67
|
-
def assemble_current_states(self):
|
67
|
+
def assemble_current_states(self) -> None:
|
68
68
|
self._current_states = defaultdict(State)
|
69
69
|
for name, client in self._cna_clients.items():
|
70
70
|
cnas = client.list_assets()
|
@@ -72,7 +72,7 @@ class CNAIntegration:
|
|
72
72
|
state.add_raw_data(cnas)
|
73
73
|
self._current_states[name] = state
|
74
74
|
|
75
|
-
def provision(self, dry_run: bool = False):
|
75
|
+
def provision(self, dry_run: bool = False) -> None:
|
76
76
|
for provisioner_name, cna_client in self._cna_clients.items():
|
77
77
|
desired_state = self._desired_states[provisioner_name]
|
78
78
|
current_state = self._current_states[provisioner_name]
|
@@ -119,7 +119,6 @@ def run(
|
|
119
119
|
dry_run: bool,
|
120
120
|
# TODO: Threadpool not used yet - will be used once we understand scopes in more detail
|
121
121
|
thread_pool_size: int,
|
122
|
-
defer=None,
|
123
122
|
) -> None:
|
124
123
|
settings = get_app_interface_vault_settings()
|
125
124
|
secret_reader = create_secret_reader(use_vault=settings.vault)
|
reconcile/cna/state.py
CHANGED
@@ -50,7 +50,7 @@ class State:
|
|
50
50
|
# pytest should show nice diff
|
51
51
|
return str(self._assets)
|
52
52
|
|
53
|
-
def _validate_addition(self, asset: Asset):
|
53
|
+
def _validate_addition(self, asset: Asset) -> None:
|
54
54
|
if asset.kind not in self._assets:
|
55
55
|
raise CNAStateError(f"State doesn't know asset_kind {asset.kind}")
|
56
56
|
if asset.name in self._assets[asset.kind]:
|
@@ -58,11 +58,11 @@ class State:
|
|
58
58
|
f"Duplicate asset name found in state: kind={asset.kind}, name={asset.name}"
|
59
59
|
)
|
60
60
|
|
61
|
-
def add_asset(self, asset: Asset):
|
61
|
+
def add_asset(self, asset: Asset) -> None:
|
62
62
|
self._validate_addition(asset=asset)
|
63
63
|
self._assets[asset.kind][asset.name] = asset
|
64
64
|
|
65
|
-
def add_raw_data(self, data: Iterable[Mapping[str, Any]]):
|
65
|
+
def add_raw_data(self, data: Iterable[Mapping[str, Any]]) -> None:
|
66
66
|
for cna in data:
|
67
67
|
asset = asset_factory_from_raw_data(cna)
|
68
68
|
self._validate_addition(asset=asset)
|