qontract-reconcile 0.10.2.dev313__py3-none-any.whl → 0.10.2.dev315__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.dev313.dist-info → qontract_reconcile-0.10.2.dev315.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev313.dist-info → qontract_reconcile-0.10.2.dev315.dist-info}/RECORD +16 -16
- reconcile/requests_sender.py +8 -3
- reconcile/sendgrid_teammates.py +20 -9
- reconcile/status.py +2 -2
- reconcile/terraform_aws_route53.py +11 -7
- reconcile/terraform_cloudflare_resources.py +6 -5
- reconcile/terraform_users.py +17 -16
- reconcile/utils/openssl.py +2 -2
- reconcile/utils/repo_owners.py +21 -29
- reconcile/utils/runtime/meta.py +2 -1
- reconcile/utils/sharding.py +1 -1
- reconcile/utils/sqs_gateway.py +14 -10
- tools/qontract_cli.py +1 -1
- {qontract_reconcile-0.10.2.dev313.dist-info → qontract_reconcile-0.10.2.dev315.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev313.dist-info → qontract_reconcile-0.10.2.dev315.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev313.dist-info → qontract_reconcile-0.10.2.dev315.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.dev315
|
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.dev313.dist-info → qontract_reconcile-0.10.2.dev315.dist-info}/RECORD
RENAMED
@@ -90,27 +90,27 @@ reconcile/quay_permissions.py,sha256=BF539lRxjpgwm88WzazklzgaCF_ipRALwbO2AdpqUqE
|
|
90
90
|
reconcile/quay_repos.py,sha256=fBleLzMtfDmTidpzbrTt8kGCy-Bk3J06EO4hhyghGnQ,7570
|
91
91
|
reconcile/queries.py,sha256=FLUZBtFC2S-e6yjtC1Oq968CJP6t3nc36NPj0wYa0bE,53472
|
92
92
|
reconcile/query_validator.py,sha256=csOSkKxcf6ZlpchJu4ck2jLYKUN6y1l-UmSQUFHgssY,1618
|
93
|
-
reconcile/requests_sender.py,sha256=
|
93
|
+
reconcile/requests_sender.py,sha256=g-tlrudvIqhneQPDMrfYF0Xsq7BSW2QcBPirl7hFM6I,4058
|
94
94
|
reconcile/resource_scraper.py,sha256=sg10j7lwAE8JxsyBTaxixOR3QYnePctsNuwOLiz4QVg,2309
|
95
95
|
reconcile/resource_template_tester.py,sha256=DsKvBuNLPxm4Fa-e1YHHySnhThm5i_j-nF3G4b02Mz0,2416
|
96
96
|
reconcile/run_integration.py,sha256=M2rIpcx7k0vGkTHdgm0h1efLOWiJ-O2WbYPHKtvIpWA,10214
|
97
97
|
reconcile/saas_file_validator.py,sha256=wmO7yni6zCiQN2micOQ1HdA0-3-N3IvBbBYLLzbNvsI,2499
|
98
|
-
reconcile/sendgrid_teammates.py,sha256=
|
98
|
+
reconcile/sendgrid_teammates.py,sha256=rknegYin7214pfqXmCALh8cd8n_qha18fGEr4_1ZFOQ,5183
|
99
99
|
reconcile/service_dependencies.py,sha256=KydjllianL0lUwhroBAPui7jrnhHSq7j2PB6CoV2nuU,4349
|
100
100
|
reconcile/signalfx_endpoint_monitoring.py,sha256=Nqgsg1cflSd2nNnm89y_e8c--7xLUqTrKOHkDs-qADE,2868
|
101
101
|
reconcile/slack_base.py,sha256=I-msunWxfgu5bSwXYulGbtLjxUB_tRmTCAUCU-3nabI,3484
|
102
102
|
reconcile/slack_usergroups.py,sha256=3uQVZK0WeZfvE1g7xQwciKCcC3LifDa3NuE1ygQ0cRk,30174
|
103
103
|
reconcile/sql_query.py,sha256=FVwANLPWjkUHqN2OXJ-vnX5hqqcO6rTdyLEO4HkmAgM,26397
|
104
|
-
reconcile/status.py,sha256=
|
104
|
+
reconcile/status.py,sha256=h73oaSxO5sftEGqFrXVAlySBvNYPWpowDaYYplcky5A,565
|
105
105
|
reconcile/status_board.py,sha256=0vTQzxrFPTmJtzNOC-iaJG_BmXbDe2vgBUe0LMUyfDE,15313
|
106
|
-
reconcile/terraform_aws_route53.py,sha256=
|
106
|
+
reconcile/terraform_aws_route53.py,sha256=p_NZDjZzOJSgFTY7KJ1qHERWaTGvFJSykY8uIYgSmVg,10183
|
107
107
|
reconcile/terraform_cloudflare_dns.py,sha256=0Eu46o_BBEEq-B-CCvKop9VTbwrvliCKGSS9gLBSJE4,13456
|
108
|
-
reconcile/terraform_cloudflare_resources.py,sha256=
|
108
|
+
reconcile/terraform_cloudflare_resources.py,sha256=HlctpWi-9NxtsO3hL9fpPpD0m5v5bgL0LRQsp7ToeAs,15047
|
109
109
|
reconcile/terraform_cloudflare_users.py,sha256=mlSYNktRetBvw8mi2TUSdKSZw0aQ821VeU6OQ1WcV3U,13516
|
110
110
|
reconcile/terraform_repo.py,sha256=vVJfaCV9775FGMMTHfoobaPetSlJMiQ4arNudL2pvh8,15607
|
111
111
|
reconcile/terraform_resources.py,sha256=AXO3_Ehcg3I6ao7qiKzXC4Mk6BqwMoNooXU50c2zSTA,19555
|
112
112
|
reconcile/terraform_tgw_attachments.py,sha256=P2HivCjT5AlyODy-fu1qAK5355nDEArE8E4NQlIlF7U,18933
|
113
|
-
reconcile/terraform_users.py,sha256=
|
113
|
+
reconcile/terraform_users.py,sha256=xa-UK2iTy0HRFAGfFQvxTbBaypsqx3O0XGVWIU9yIxI,10659
|
114
114
|
reconcile/terraform_vpc_peerings.py,sha256=rMotDHy3Fd5QTxrOGjCJ3f2vICk3fmxrKYVCIU8p_y4,27787
|
115
115
|
reconcile/vault_replication.py,sha256=trtbB-jDwca822J5I_s0zlwFtlyaiAtqgbPeqp7Cggc,17714
|
116
116
|
reconcile/vpc_peerings_validator.py,sha256=_77eu6DSy6VjTE5mhV-sOIVOGIiBvDEEDCdwwRdrgVQ,7101
|
@@ -633,7 +633,7 @@ reconcile/utils/oc_filters.py,sha256=Tz3OwtbUaYKmxENFls5CtPVzkZDeFXknw53dJe-wbT8
|
|
633
633
|
reconcile/utils/oc_map.py,sha256=ougQ-Wlsa8ymoE_lPQ7g2LlpsUOsHVeRCLYW_6fjeWU,8976
|
634
634
|
reconcile/utils/ocm_base_client.py,sha256=t5kxhklEqOpenXPkXiwQIk8d3D7hIUndBm5qGusS0bc,6681
|
635
635
|
reconcile/utils/openshift_resource.py,sha256=Nbte4oCzxL27Hrt2vNs2ybV3X3pV4vGJEnErEsiA6UY,24810
|
636
|
-
reconcile/utils/openssl.py,sha256=
|
636
|
+
reconcile/utils/openssl.py,sha256=qdEdSmNXDgx_hhj2psEea6O12cmn3pb4GNhQJtI5l_E,399
|
637
637
|
reconcile/utils/output.py,sha256=wvsyf8NsFTaFHNkc8to75ta8f474Y4TMO4cHyAHEePk,2209
|
638
638
|
reconcile/utils/pagerduty_api.py,sha256=6Ae-KjcmA6Bf328UhTdQ2VwYjh4uFIW1NdZW6PUgT-c,7607
|
639
639
|
reconcile/utils/parse_dhms_duration.py,sha256=TONpLnec5gHeF7k815YNJpQyDjXhkxZIcv9s8ffbTSY,1840
|
@@ -644,17 +644,17 @@ reconcile/utils/promtool.py,sha256=YnqwMAzsQVGuBZ1j9zy3UcVPFQVJgBMLzQkxhK_KFkU,3
|
|
644
644
|
reconcile/utils/quay_api.py,sha256=ZWjfjzFnIsbKRDcdAnP9tWQezclf53I7VWZJ0gbF2kE,8260
|
645
645
|
reconcile/utils/quay_mirror.py,sha256=dpWCNv5lITwIk6Q9RkmqaQKHNk_JPy27UQEribJ7E-U,1324
|
646
646
|
reconcile/utils/raw_github_api.py,sha256=2WKtE8ABYYB9UGOAh9N_kLkksBWL3320Z2_scteZddI,2805
|
647
|
-
reconcile/utils/repo_owners.py,sha256=
|
647
|
+
reconcile/utils/repo_owners.py,sha256=c6Z-U5TkiRPvuhr_zYWvZG9HZGzoT-l-d2PJ33lGflE,6507
|
648
648
|
reconcile/utils/rest_api_base.py,sha256=MT7tp6CQO2S5aKfVOzw_hipWg7wAGoOqkm4qurI1hEU,4342
|
649
649
|
reconcile/utils/rhcsv2_certs.py,sha256=ZnlUlEI2k6UrljGarkm1ey0znMlQtjeZB7VEfCH1A64,2545
|
650
650
|
reconcile/utils/ruamel.py,sha256=FzL4_L0FnMOUZmgThrZSMJs5MTdXwiy-E9MZWfk8bh8,397
|
651
651
|
reconcile/utils/secret_reader.py,sha256=vCU-g7q1Fbd5qOUMn7TAeE5yWhlmXme0OzZgyxk7tkY,10306
|
652
652
|
reconcile/utils/semver_helper.py,sha256=-WfPOMSA2v1h7hT3PwVf-Htg7wOsoKlQC1JdmDX2Ars,1268
|
653
|
-
reconcile/utils/sharding.py,sha256=
|
653
|
+
reconcile/utils/sharding.py,sha256=_0AsDQ_fi9lYjI8MJABP1FaMjJQ3L93xBUDWx5e3DDw,586
|
654
654
|
reconcile/utils/slack_api.py,sha256=fcqdi9cKRpibT5FlaeOY5iBQ3Dnni55u1Va9HcQC3Ls,17863
|
655
655
|
reconcile/utils/slo_document_manager.py,sha256=YqiCYA_kRq5_oNc_VTYipjbph4k0XHDcjwbbcdaW1ag,9563
|
656
656
|
reconcile/utils/smtp_client.py,sha256=0xefB4I9E5eBB-FlxFJYjvz3Kvuqi_K3Ma_Wk0NAQKM,2779
|
657
|
-
reconcile/utils/sqs_gateway.py,sha256=
|
657
|
+
reconcile/utils/sqs_gateway.py,sha256=x0dGIJeuMTsIKhHyosVPqi_POX0IJ9OWVqAHRa55dxI,2551
|
658
658
|
reconcile/utils/state.py,sha256=vCHYIfrWLfPyIWEHSaADWlc4OqhwcOiqM3Egqvw-lfo,16372
|
659
659
|
reconcile/utils/structs.py,sha256=P57POzpEntu8ZoZDnsOdni9qUuBDWknmw0iinznxXoY,386
|
660
660
|
reconcile/utils/terraform_client.py,sha256=zF_F31WzDA3fjNPj_Jl6mQJMfI3wEQ0gsurtrjqh4Ds,37684
|
@@ -744,7 +744,7 @@ reconcile/utils/runtime/__init__.py,sha256=sfk92MGfsBh9tKYHl_FH17NdEsrGBwgDFTb7K
|
|
744
744
|
reconcile/utils/runtime/desired_state_diff.py,sha256=Bw4zqel-klXCMZGqD1gyh8zkFq4h5qzv8rJn7K6WTXs,8132
|
745
745
|
reconcile/utils/runtime/environment.py,sha256=h-CFKLK1qRl_gfOVIUwjqVNOmukIPzUG7AiqpJGrjHA,2038
|
746
746
|
reconcile/utils/runtime/integration.py,sha256=I74KlnsNKd7Hf8rBRug6blXkGKidSDQEjqHRLAfgTXI,10973
|
747
|
-
reconcile/utils/runtime/meta.py,sha256=
|
747
|
+
reconcile/utils/runtime/meta.py,sha256=M_EOxrb0KhQA4TwpHekbog2jOZqaBPVTIijXyRuMjn0,255
|
748
748
|
reconcile/utils/runtime/runner.py,sha256=OGT57aCwspAjdjGXtpbQnTmJeeWnRh9a2N73TLp4jnM,7880
|
749
749
|
reconcile/utils/runtime/sharding.py,sha256=r0ieUtNed7NvknSw6qQrCkKpVXE1shuHGnfFcnpA_k4,16142
|
750
750
|
reconcile/utils/saasherder/__init__.py,sha256=3U8plqMAPRE1kjwZ5YnIsYsggTf4_gS7flRUEuXVBAs,343
|
@@ -770,7 +770,7 @@ tools/app_sre_tekton_access_reporter.py,sha256=5qmkevJdlb2j_lpGC5Pu1Pmo0eomX5Zxz
|
|
770
770
|
tools/app_sre_tekton_access_revalidation.py,sha256=vwL1o_j7oSTOhrHNH1znpgjA2LHGzb8yc5iG3aaY4m0,2684
|
771
771
|
tools/glitchtip_access_reporter.py,sha256=wnaiDGW4MkYONV_erltnJ6nGkEj0kQrAiv04NNnOS0k,2859
|
772
772
|
tools/glitchtip_access_revalidation.py,sha256=jjeLO53LTbz_LfQw3G2Cs8lVLO_6xqU39BYyTH3cEPE,2764
|
773
|
-
tools/qontract_cli.py,sha256=
|
773
|
+
tools/qontract_cli.py,sha256=T_BEnJZt23_XeaQYZZxUvPiCAroe_RPtU43wJTPqXFg,159891
|
774
774
|
tools/template_validation.py,sha256=Xn9X4sGFznx-rvBDnq9Kq16rfET8V3bqH1EwavsGBac,3335
|
775
775
|
tools/cli_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
776
776
|
tools/cli_commands/container_images_report.py,sha256=8mAjCS6XR0yD7k0mfiVBlt6xbYU47q_ftdYNi5o5VKE,5566
|
@@ -796,7 +796,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
796
796
|
tools/saas_promotion_state/saas_promotion_state.py,sha256=uQv2QJAmUXP1g2GPIH30WTlvL9soY6m9lefpZEVDM5w,3965
|
797
797
|
tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
|
798
798
|
tools/sre_checkpoints/util.py,sha256=KcYVfa3UmJHVP_ocgrKe8NkrO5IDB9aWEDydSokPcRk,975
|
799
|
-
qontract_reconcile-0.10.2.
|
800
|
-
qontract_reconcile-0.10.2.
|
801
|
-
qontract_reconcile-0.10.2.
|
802
|
-
qontract_reconcile-0.10.2.
|
799
|
+
qontract_reconcile-0.10.2.dev315.dist-info/METADATA,sha256=AE42AC4sotdY4LzNv1wIEFqqW1Qt8h1onk91ARjO-YQ,24916
|
800
|
+
qontract_reconcile-0.10.2.dev315.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
801
|
+
qontract_reconcile-0.10.2.dev315.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
802
|
+
qontract_reconcile-0.10.2.dev315.dist-info/RECORD,,
|
reconcile/requests_sender.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
|
+
from collections.abc import Callable, Mapping
|
3
4
|
from subprocess import CalledProcessError
|
5
|
+
from typing import Any
|
4
6
|
|
5
7
|
from reconcile import (
|
6
8
|
queries,
|
@@ -44,7 +46,9 @@ Encrypted credentials:
|
|
44
46
|
"""
|
45
47
|
|
46
48
|
|
47
|
-
def get_encrypted_credentials(
|
49
|
+
def get_encrypted_credentials(
|
50
|
+
credentials_name: str, user: Mapping[str, Any], settings: Mapping[str, Any]
|
51
|
+
) -> str | None:
|
48
52
|
credentials_map = settings["credentials"]
|
49
53
|
credentials_map_item = [c for c in credentials_map if c["name"] == credentials_name]
|
50
54
|
if len(credentials_map_item) != 1:
|
@@ -59,7 +63,7 @@ def get_encrypted_credentials(credentials_name, user, settings):
|
|
59
63
|
|
60
64
|
|
61
65
|
@defer
|
62
|
-
def run(dry_run, defer=None):
|
66
|
+
def run(dry_run: bool, defer: Callable | None = None) -> None:
|
63
67
|
settings = queries.get_app_interface_settings()
|
64
68
|
vault_settings = get_app_interface_vault_settings()
|
65
69
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
@@ -76,7 +80,8 @@ def run(dry_run, defer=None):
|
|
76
80
|
integration=QONTRACT_INTEGRATION,
|
77
81
|
secret_reader=secret_reader,
|
78
82
|
)
|
79
|
-
defer
|
83
|
+
if defer:
|
84
|
+
defer(state.cleanup)
|
80
85
|
credentials_requests = queries.get_credentials_requests()
|
81
86
|
|
82
87
|
# validate no 2 requests have the same name
|
reconcile/sendgrid_teammates.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
|
+
from collections.abc import Iterable, Mapping
|
4
|
+
from typing import Any
|
3
5
|
|
4
6
|
import sendgrid
|
5
7
|
from sretoolbox.utils import retry
|
@@ -17,18 +19,22 @@ class SendGridAPIError(Exception):
|
|
17
19
|
|
18
20
|
|
19
21
|
class Teammate:
|
20
|
-
def __init__(
|
22
|
+
def __init__(
|
23
|
+
self, email: str, pending_token: str | None = None, username: str | None = None
|
24
|
+
) -> None:
|
21
25
|
self.email = email
|
22
|
-
self.username = username or email.split("@")[0]
|
26
|
+
self.username = username or email.split("@", maxsplit=1)[0]
|
23
27
|
self.pending_token = pending_token
|
24
28
|
|
25
29
|
@property
|
26
|
-
def pending(self):
|
30
|
+
def pending(self) -> bool:
|
27
31
|
return bool(self.pending_token)
|
28
32
|
|
29
33
|
|
30
|
-
def fetch_desired_state(
|
31
|
-
|
34
|
+
def fetch_desired_state(
|
35
|
+
users: Iterable[Mapping[str, Any]],
|
36
|
+
) -> dict[str, list[Teammate]]:
|
37
|
+
desired_state: dict[str, list[Teammate]] = {}
|
32
38
|
for user in users:
|
33
39
|
roles = user.get("roles") or []
|
34
40
|
for role in roles:
|
@@ -42,7 +48,7 @@ def fetch_desired_state(users):
|
|
42
48
|
|
43
49
|
|
44
50
|
@retry()
|
45
|
-
def fetch_current_state(sg_client):
|
51
|
+
def fetch_current_state(sg_client: sendgrid.SendGridAPIClient) -> list[Teammate]:
|
46
52
|
state = []
|
47
53
|
limit = 100
|
48
54
|
|
@@ -79,7 +85,7 @@ def fetch_current_state(sg_client):
|
|
79
85
|
return state
|
80
86
|
|
81
87
|
|
82
|
-
def raise_if_error(response):
|
88
|
+
def raise_if_error(response: Any) -> None:
|
83
89
|
"""
|
84
90
|
Raises an SendGridAPIError if the request has returned an error
|
85
91
|
"""
|
@@ -87,7 +93,12 @@ def raise_if_error(response):
|
|
87
93
|
raise SendGridAPIError(response.body.decode("utf-8"))
|
88
94
|
|
89
95
|
|
90
|
-
def act(
|
96
|
+
def act(
|
97
|
+
dry_run: bool,
|
98
|
+
sg_client: sendgrid.SendGridAPIClient,
|
99
|
+
desired_state: Iterable[Teammate],
|
100
|
+
current_state: Iterable[Teammate],
|
101
|
+
) -> bool:
|
91
102
|
"""
|
92
103
|
Reconciles current state with desired state.
|
93
104
|
|
@@ -145,7 +156,7 @@ def act(dry_run, sg_client, desired_state, current_state):
|
|
145
156
|
return error
|
146
157
|
|
147
158
|
|
148
|
-
def run(dry_run):
|
159
|
+
def run(dry_run: bool) -> None:
|
149
160
|
settings = queries.get_app_interface_settings()
|
150
161
|
secret_reader = SecretReader(settings=settings)
|
151
162
|
|
reconcile/status.py
CHANGED
@@ -11,7 +11,7 @@ class ExitCodes:
|
|
11
11
|
class _RunningState:
|
12
12
|
_state: dict[Any, Any] = {}
|
13
13
|
|
14
|
-
def __init__(self):
|
14
|
+
def __init__(self) -> None:
|
15
15
|
self.__dict__ = self._state
|
16
16
|
|
17
17
|
|
@@ -22,7 +22,7 @@ class RunningState(_RunningState):
|
|
22
22
|
by the callers.
|
23
23
|
"""
|
24
24
|
|
25
|
-
def __getattr__(self, item):
|
25
|
+
def __getattr__(self, item: str) -> None:
|
26
26
|
"""
|
27
27
|
Default value for attributes not explicitly created is None.
|
28
28
|
"""
|
@@ -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
|
)
|
@@ -25,8 +26,10 @@ QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
|
|
25
26
|
|
26
27
|
|
27
28
|
def build_desired_state(
|
28
|
-
zones: Iterable[Mapping
|
29
|
-
|
29
|
+
zones: Iterable[Mapping[str, Any]],
|
30
|
+
all_accounts: Iterable[Mapping[str, Any]],
|
31
|
+
settings: Mapping[str, Any],
|
32
|
+
) -> list[dict[str, Any]]:
|
30
33
|
"""
|
31
34
|
Build the desired state from the app-interface resources
|
32
35
|
|
@@ -36,7 +39,7 @@ def build_desired_state(
|
|
36
39
|
:rtype: list of dict
|
37
40
|
"""
|
38
41
|
|
39
|
-
desired_state = []
|
42
|
+
desired_state: list[dict[str, Any]] = []
|
40
43
|
for zone in zones:
|
41
44
|
account = zone["account"]
|
42
45
|
account_name = account["name"]
|
@@ -208,8 +211,8 @@ def run(
|
|
208
211
|
enable_deletion: bool = True,
|
209
212
|
thread_pool_size: int = DEFAULT_THREAD_POOL_SIZE,
|
210
213
|
account_name: str | None = None,
|
211
|
-
defer=None,
|
212
|
-
):
|
214
|
+
defer: Callable | None = None,
|
215
|
+
) -> None:
|
213
216
|
settings = queries.get_app_interface_settings()
|
214
217
|
zones = queries.get_dns_zones(account_name=account_name)
|
215
218
|
|
@@ -255,7 +258,8 @@ def run(
|
|
255
258
|
if tf is None:
|
256
259
|
sys.exit(ExitCodes.ERROR)
|
257
260
|
|
258
|
-
defer
|
261
|
+
if defer:
|
262
|
+
defer(tf.cleanup)
|
259
263
|
|
260
264
|
_, err = tf.plan(enable_deletion)
|
261
265
|
if err:
|
@@ -269,7 +273,7 @@ def run(
|
|
269
273
|
sys.exit(ExitCodes.ERROR)
|
270
274
|
|
271
275
|
|
272
|
-
def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
|
276
|
+
def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
273
277
|
return {
|
274
278
|
"zones": queries.get_dns_zones(),
|
275
279
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
|
-
from collections.abc import Iterable
|
3
|
+
from collections.abc import Callable, Iterable
|
4
4
|
from typing import (
|
5
5
|
Any,
|
6
6
|
cast,
|
@@ -193,7 +193,7 @@ def _populate_oc_resources(
|
|
193
193
|
spec: CurrentStateSpec,
|
194
194
|
ri: ResourceInventory,
|
195
195
|
account_names: Iterable[str] | None,
|
196
|
-
):
|
196
|
+
) -> None:
|
197
197
|
"""
|
198
198
|
This was taken from terraform_resources and might be a later candidate for DRY.
|
199
199
|
"""
|
@@ -315,7 +315,7 @@ def run(
|
|
315
315
|
vault_output_path: str = "",
|
316
316
|
internal: bool | None = None,
|
317
317
|
use_jump_host: bool = True,
|
318
|
-
defer=None,
|
318
|
+
defer: Callable | None = None,
|
319
319
|
) -> None:
|
320
320
|
vault_settings = get_app_interface_vault_settings()
|
321
321
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
@@ -392,7 +392,8 @@ def run(
|
|
392
392
|
working_dirs,
|
393
393
|
thread_pool_size,
|
394
394
|
)
|
395
|
-
defer
|
395
|
+
if defer:
|
396
|
+
defer(tf.cleanup)
|
396
397
|
|
397
398
|
disabled_deletions_detected, err = tf.plan(enable_deletion)
|
398
399
|
if err:
|
@@ -440,7 +441,7 @@ def _get_cloudflare_desired_state() -> tuple[
|
|
440
441
|
return query_accounts, query_resources
|
441
442
|
|
442
443
|
|
443
|
-
def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
|
444
|
+
def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
444
445
|
desired_state = _get_cloudflare_desired_state()
|
445
446
|
|
446
447
|
return {state.__repr_name__(): state.dict() for state in desired_state}
|
reconcile/terraform_users.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import sys
|
2
|
+
from collections.abc import Iterable, Mapping
|
2
3
|
from textwrap import indent
|
3
4
|
from typing import (
|
4
5
|
Any,
|
@@ -95,9 +96,9 @@ def get_tf_roles() -> list[Role]:
|
|
95
96
|
|
96
97
|
|
97
98
|
def _filter_participating_aws_accounts(
|
98
|
-
accounts:
|
99
|
-
roles:
|
100
|
-
) -> list:
|
99
|
+
accounts: Iterable[dict[str, Any]],
|
100
|
+
roles: Iterable[Mapping[str, Any]],
|
101
|
+
) -> list[dict[str, Any]]:
|
101
102
|
participating_aws_account_names: set[str] = set()
|
102
103
|
for role in roles:
|
103
104
|
participating_aws_account_names.update(
|
@@ -111,7 +112,7 @@ def _filter_participating_aws_accounts(
|
|
111
112
|
|
112
113
|
|
113
114
|
def setup(
|
114
|
-
print_to_file,
|
115
|
+
print_to_file: str | None,
|
115
116
|
thread_pool_size: int,
|
116
117
|
skip_reencrypt_accounts: list[str],
|
117
118
|
appsre_pgp_key: str | None = None,
|
@@ -146,10 +147,10 @@ def setup(
|
|
146
147
|
|
147
148
|
|
148
149
|
def send_email_invites(
|
149
|
-
new_users,
|
150
|
+
new_users: Iterable[tuple[str, str, str, str]],
|
150
151
|
smtp_client: SmtpClient,
|
151
|
-
skip_reencrypt_accounts:
|
152
|
-
):
|
152
|
+
skip_reencrypt_accounts: Iterable[str],
|
153
|
+
) -> None:
|
153
154
|
msg_template = """
|
154
155
|
You have been invited to join the {} AWS account!
|
155
156
|
Below you will find credentials for the first sign in.
|
@@ -189,9 +190,9 @@ Encrypted password: {}
|
|
189
190
|
def write_user_to_vault(
|
190
191
|
vault_client: _VaultClient,
|
191
192
|
vault_path: str,
|
192
|
-
new_users:
|
193
|
-
skip_reencrypt_accounts:
|
194
|
-
):
|
193
|
+
new_users: Iterable[tuple[str, str, str, str]],
|
194
|
+
skip_reencrypt_accounts: Iterable[str],
|
195
|
+
) -> None:
|
195
196
|
for account, console_url, user_name, enc_password in new_users:
|
196
197
|
if account in skip_reencrypt_accounts:
|
197
198
|
continue
|
@@ -208,13 +209,13 @@ def write_user_to_vault(
|
|
208
209
|
vault_client.write(desired_secret, decode_base64=False)
|
209
210
|
|
210
211
|
|
211
|
-
def cleanup_and_exit(tf=None, status=False):
|
212
|
+
def cleanup_and_exit(tf: Terraform | None = None, status: bool = False) -> None:
|
212
213
|
if tf is not None:
|
213
214
|
tf.cleanup()
|
214
215
|
sys.exit(status)
|
215
216
|
|
216
217
|
|
217
|
-
def get_reencrypt_settings():
|
218
|
+
def get_reencrypt_settings() -> tuple[list[str], str | None, Any]:
|
218
219
|
all_reencrypt_settings = query(
|
219
220
|
query_func=gql.get_api().query
|
220
221
|
).pgp_reencryption_settings
|
@@ -243,7 +244,7 @@ def run(
|
|
243
244
|
thread_pool_size: int = DEFAULT_THREAD_POOL_SIZE,
|
244
245
|
send_mails: bool = True,
|
245
246
|
account_name: str | None = None,
|
246
|
-
):
|
247
|
+
) -> None:
|
247
248
|
skip_accounts, appsre_pgp_key, reencrypt_settings = get_reencrypt_settings()
|
248
249
|
|
249
250
|
# setup errors should skip resources that will lead
|
@@ -319,7 +320,7 @@ def run(
|
|
319
320
|
cleanup_and_exit(tf, setup_err)
|
320
321
|
|
321
322
|
|
322
|
-
def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
|
323
|
+
def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
323
324
|
"""
|
324
325
|
Finding diffs in deeply nested structures is time/resource consuming.
|
325
326
|
Having a unique known property to identify objects makes it easier to match
|
@@ -330,11 +331,11 @@ def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
|
|
330
331
|
for the DeepDiff library used in qontract-reconcile.
|
331
332
|
"""
|
332
333
|
|
333
|
-
def add_account_identity(acc):
|
334
|
+
def add_account_identity(acc: dict[str, Any]) -> dict[str, Any]:
|
334
335
|
acc[IDENTIFIER_FIELD_NAME] = acc["path"]
|
335
336
|
return acc
|
336
337
|
|
337
|
-
def add_role_identity(role):
|
338
|
+
def add_role_identity(role: dict[str, Any]) -> dict[str, Any]:
|
338
339
|
role[IDENTIFIER_FIELD_NAME] = role["name"]
|
339
340
|
return role
|
340
341
|
|
reconcile/utils/openssl.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
from OpenSSL import crypto
|
2
2
|
|
3
3
|
|
4
|
-
def certificate_matches_host(certificate, host):
|
4
|
+
def certificate_matches_host(certificate: bytes, host: str) -> bool:
|
5
5
|
common_name = get_certificate_common_name(certificate)
|
6
6
|
return host.endswith(common_name.replace("*.", ""))
|
7
7
|
|
8
8
|
|
9
|
-
def get_certificate_common_name(certificate):
|
9
|
+
def get_certificate_common_name(certificate: bytes) -> str:
|
10
10
|
cert = crypto.load_certificate(crypto.FILETYPE_PEM, certificate)
|
11
11
|
subject = cert.get_subject()
|
12
12
|
return subject.CN
|
reconcile/utils/repo_owners.py
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
import logging
|
2
2
|
import os
|
3
3
|
import pathlib
|
4
|
+
from collections.abc import Iterable, Mapping
|
4
5
|
|
5
6
|
from ruamel import yaml
|
6
7
|
|
8
|
+
from reconcile.utils.github_api import GithubRepositoryApi
|
9
|
+
from reconcile.utils.gitlab_api import GitLabApi
|
10
|
+
|
7
11
|
_LOG = logging.getLogger(__name__)
|
8
12
|
|
9
13
|
|
@@ -12,38 +16,24 @@ class RepoOwners:
|
|
12
16
|
Abstracts the owners of a repository with per-path granularity.
|
13
17
|
"""
|
14
18
|
|
15
|
-
def __init__(
|
19
|
+
def __init__(
|
20
|
+
self,
|
21
|
+
git_cli: GitLabApi | GithubRepositoryApi,
|
22
|
+
ref: str = "master",
|
23
|
+
recursive: bool = True,
|
24
|
+
) -> None:
|
16
25
|
self._git_cli = git_cli
|
17
26
|
self._ref = ref
|
18
|
-
self._owners_map = None
|
27
|
+
self._owners_map: dict[str, dict[str, set[str]]] | None = None
|
19
28
|
self._recursive = recursive
|
20
29
|
|
21
30
|
@property
|
22
|
-
def owners_map(self):
|
31
|
+
def owners_map(self) -> dict[str, dict[str, set[str]]]:
|
23
32
|
if self._owners_map is None:
|
24
33
|
self._owners_map = self._get_owners_map()
|
25
34
|
return self._owners_map
|
26
35
|
|
27
|
-
def
|
28
|
-
"""
|
29
|
-
Gets all the owners of the repository.
|
30
|
-
|
31
|
-
:return: the repository owners
|
32
|
-
:rtype: dict
|
33
|
-
"""
|
34
|
-
repo_owners = {"approvers": set(), "reviewers": set()}
|
35
|
-
|
36
|
-
if "." in self.owners_map:
|
37
|
-
repo_owners["approvers"].update(self.owners_map["."]["approvers"])
|
38
|
-
repo_owners["reviewers"].update(self.owners_map["."]["reviewers"])
|
39
|
-
|
40
|
-
for owners in self.owners_map.values():
|
41
|
-
repo_owners["approvers"].update(owners["approvers"])
|
42
|
-
repo_owners["reviewers"].update(owners["reviewers"])
|
43
|
-
|
44
|
-
return repo_owners
|
45
|
-
|
46
|
-
def get_root_owners(self):
|
36
|
+
def get_root_owners(self) -> dict[str, list[str]]:
|
47
37
|
"""
|
48
38
|
Gets all the owners defined in the repository root.
|
49
39
|
|
@@ -56,7 +46,7 @@ class RepoOwners:
|
|
56
46
|
|
57
47
|
return {"approvers": [], "reviewers": []}
|
58
48
|
|
59
|
-
def get_path_owners(self, path):
|
49
|
+
def get_path_owners(self, path: str) -> dict[str, list[str]]:
|
60
50
|
"""
|
61
51
|
Gets all the owners of a given path, no matter in which
|
62
52
|
level of the filesystem tree the owner was specified.
|
@@ -67,7 +57,7 @@ class RepoOwners:
|
|
67
57
|
:return: the path owners
|
68
58
|
:rtype: dict
|
69
59
|
"""
|
70
|
-
path_owners = {"approvers": set(), "reviewers": set()}
|
60
|
+
path_owners: dict[str, set[str]] = {"approvers": set(), "reviewers": set()}
|
71
61
|
|
72
62
|
if "." in self.owners_map:
|
73
63
|
path_owners["approvers"].update(self.owners_map["."]["approvers"])
|
@@ -80,7 +70,7 @@ class RepoOwners:
|
|
80
70
|
|
81
71
|
return self._set_to_sorted_list(path_owners)
|
82
72
|
|
83
|
-
def get_path_closest_owners(self, path):
|
73
|
+
def get_path_closest_owners(self, path: str) -> dict[str, list[str]]:
|
84
74
|
"""
|
85
75
|
Gets all closest owners of a given path, no matter in which
|
86
76
|
level of the filesystem tree the owner was specified.
|
@@ -108,7 +98,7 @@ class RepoOwners:
|
|
108
98
|
|
109
99
|
return {"approvers": [], "reviewers": []}
|
110
100
|
|
111
|
-
def _get_owners_map(self):
|
101
|
+
def _get_owners_map(self) -> dict[str, dict[str, set[str]]]:
|
112
102
|
"""
|
113
103
|
Maps all the OWNERS files content to their respective
|
114
104
|
owned directory.
|
@@ -173,7 +163,7 @@ class RepoOwners:
|
|
173
163
|
}
|
174
164
|
return owners_map
|
175
165
|
|
176
|
-
def _get_aliases(self):
|
166
|
+
def _get_aliases(self) -> dict[str, list[str]] | None:
|
177
167
|
"""
|
178
168
|
Retrieves the approvers aliases from the OWNERS_ALIASES file.
|
179
169
|
|
@@ -191,7 +181,9 @@ class RepoOwners:
|
|
191
181
|
return aliases["aliases"]
|
192
182
|
|
193
183
|
@staticmethod
|
194
|
-
def _set_to_sorted_list(
|
184
|
+
def _set_to_sorted_list(
|
185
|
+
owners: Mapping[str, Iterable[str]],
|
186
|
+
) -> dict[str, list[str]]:
|
195
187
|
approvers = owners["approvers"]
|
196
188
|
sorted_approvers = sorted(approvers) if approvers else []
|
197
189
|
|
reconcile/utils/runtime/meta.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import dataclasses
|
2
2
|
from dataclasses import dataclass
|
3
|
+
from typing import Any
|
3
4
|
|
4
5
|
|
5
6
|
@dataclass
|
@@ -8,5 +9,5 @@ class IntegrationMeta:
|
|
8
9
|
args: list[str]
|
9
10
|
short_help: str | None
|
10
11
|
|
11
|
-
def to_dict(self):
|
12
|
+
def to_dict(self) -> dict[str, Any]:
|
12
13
|
return dataclasses.asdict(self)
|
reconcile/utils/sharding.py
CHANGED
reconcile/utils/sqs_gateway.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import json
|
2
2
|
import os
|
3
|
+
from collections.abc import Iterable, Mapping
|
4
|
+
from typing import Any, Self
|
3
5
|
|
4
6
|
from reconcile.utils.aws_api import AWSApi
|
5
7
|
from reconcile.utils.secret_reader import SecretReader
|
@@ -12,7 +14,9 @@ class SQSGatewayInitError(Exception):
|
|
12
14
|
class SQSGateway:
|
13
15
|
"""Wrapper around SQS AWS SDK"""
|
14
16
|
|
15
|
-
def __init__(
|
17
|
+
def __init__(
|
18
|
+
self, accounts: Iterable[Mapping[str, Any]], secret_reader: SecretReader
|
19
|
+
) -> None:
|
16
20
|
queue_url = os.environ.get("gitlab_pr_submitter_queue_url") # noqa: SIM112
|
17
21
|
if not queue_url:
|
18
22
|
raise SQSGatewayInitError(
|
@@ -30,17 +34,17 @@ class SQSGateway:
|
|
30
34
|
self.sqs = self._aws_api.get_session_client(session, "sqs")
|
31
35
|
self.queue_url = queue_url
|
32
36
|
|
33
|
-
def __enter__(self):
|
37
|
+
def __enter__(self) -> Self:
|
34
38
|
return self
|
35
39
|
|
36
|
-
def __exit__(self, *ext):
|
40
|
+
def __exit__(self, *ext: Any) -> None:
|
37
41
|
self.cleanup()
|
38
42
|
|
39
|
-
def cleanup(self):
|
43
|
+
def cleanup(self) -> None:
|
40
44
|
self._aws_api.cleanup()
|
41
45
|
|
42
46
|
@staticmethod
|
43
|
-
def get_queue_account(accounts, queue_url):
|
47
|
+
def get_queue_account(accounts: Iterable[Mapping[str, Any]], queue_url: str) -> str:
|
44
48
|
queue_account_uid = queue_url.split("/")[3]
|
45
49
|
queue_account_name = [
|
46
50
|
a["name"] for a in accounts if a["uid"] == queue_account_uid
|
@@ -49,14 +53,14 @@ class SQSGateway:
|
|
49
53
|
raise SQSGatewayInitError(f"account uid not found: {queue_account_uid}")
|
50
54
|
return queue_account_name[0]
|
51
55
|
|
52
|
-
def send_message(self, body):
|
56
|
+
def send_message(self, body: Mapping[str, Any]) -> None:
|
53
57
|
self.sqs.send_message(QueueUrl=self.queue_url, MessageBody=json.dumps(body))
|
54
58
|
|
55
59
|
def receive_messages(
|
56
60
|
self,
|
57
|
-
visibility_timeout=30,
|
58
|
-
wait_time_seconds=20,
|
59
|
-
):
|
61
|
+
visibility_timeout: int = 30,
|
62
|
+
wait_time_seconds: int = 20,
|
63
|
+
) -> list[tuple[str, dict[str, Any]]]:
|
60
64
|
messages = self.sqs.receive_message(
|
61
65
|
QueueUrl=self.queue_url,
|
62
66
|
VisibilityTimeout=visibility_timeout,
|
@@ -64,5 +68,5 @@ class SQSGateway:
|
|
64
68
|
).get("Messages", [])
|
65
69
|
return [(m["ReceiptHandle"], json.loads(m["Body"])) for m in messages]
|
66
70
|
|
67
|
-
def delete_message(self, receipt_handle):
|
71
|
+
def delete_message(self, receipt_handle: str) -> None:
|
68
72
|
self.sqs.delete_message(QueueUrl=self.queue_url, ReceiptHandle=receipt_handle)
|
tools/qontract_cli.py
CHANGED
@@ -1299,7 +1299,7 @@ def user_credentials_migrate_output(ctx: click.Context, account_name: str) -> No
|
|
1299
1299
|
skip_accounts, appsre_pgp_key, _ = tfu.get_reencrypt_settings()
|
1300
1300
|
|
1301
1301
|
accounts, working_dirs, _, aws_api = tfu.setup(
|
1302
|
-
|
1302
|
+
None,
|
1303
1303
|
1,
|
1304
1304
|
skip_accounts,
|
1305
1305
|
account_name=account_name,
|
{qontract_reconcile-0.10.2.dev313.dist-info → qontract_reconcile-0.10.2.dev315.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|