qontract-reconcile 0.10.2.dev291__py3-none-any.whl → 0.10.2.dev293__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.dev291.dist-info → qontract_reconcile-0.10.2.dev293.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev291.dist-info → qontract_reconcile-0.10.2.dev293.dist-info}/RECORD +10 -10
- reconcile/gql_definitions/introspection.json +36 -0
- reconcile/gql_definitions/templating/template_collection.py +2 -0
- reconcile/gql_definitions/templating/templates.py +2 -0
- reconcile/templating/lib/rendering.py +75 -54
- reconcile/templating/renderer.py +6 -3
- reconcile/utils/terrascript_aws_client.py +107 -45
- {qontract_reconcile-0.10.2.dev291.dist-info → qontract_reconcile-0.10.2.dev293.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev291.dist-info → qontract_reconcile-0.10.2.dev293.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev291.dist-info → qontract_reconcile-0.10.2.dev293.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.dev293
|
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.dev291.dist-info → qontract_reconcile-0.10.2.dev293.dist-info}/RECORD
RENAMED
@@ -213,7 +213,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=d3PMy-mQSbSZdIGAVaZCA2U
|
|
213
213
|
reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
214
214
|
reconcile/glitchtip_project_dsn/integration.py,sha256=3GgcqUM6hWhLpo9Yx5Xr9vrdexF-WNevVCNL9bJ0Upc,8162
|
215
215
|
reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
216
|
-
reconcile/gql_definitions/introspection.json,sha256=
|
216
|
+
reconcile/gql_definitions/introspection.json,sha256=CQAoUjEbdjRlHyYeLjs1PTMiP_RQrPzD0yCj08aYawA,2348381
|
217
217
|
reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
218
218
|
reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
|
219
219
|
reconcile/gql_definitions/acs/acs_policies.py,sha256=Ygpfl2-VkYLSlJvHgp_dJBfb66K_Rwfdfpsa18w1v1s,4338
|
@@ -409,8 +409,8 @@ reconcile/gql_definitions/status_board/status_board.py,sha256=BYq-1g_-AjNKHIKmY2
|
|
409
409
|
reconcile/gql_definitions/statuspage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
410
410
|
reconcile/gql_definitions/statuspage/statuspages.py,sha256=CTRzjiR9k41LqlkgyoNHwC2JERsoD_Run_aK7jw_Ono,5299
|
411
411
|
reconcile/gql_definitions/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
412
|
-
reconcile/gql_definitions/templating/template_collection.py,sha256=
|
413
|
-
reconcile/gql_definitions/templating/templates.py,sha256=
|
412
|
+
reconcile/gql_definitions/templating/template_collection.py,sha256=alQA1qLhL0nOFcnA0O2Z7HCuuAviZXM66t6yeur9XWo,4123
|
413
|
+
reconcile/gql_definitions/templating/templates.py,sha256=rQ14gs5dMttxVuW5q26p23Y8c5vCNh8dSec9ucTGlKc,3372
|
414
414
|
reconcile/gql_definitions/terraform_cloudflare_dns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
415
415
|
reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py,sha256=eyGX9HcTF6MZbOYZ6Kl6Mg3k6nJTUtwqs9gDxBP_8Dk,1920
|
416
416
|
reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py,sha256=dBQ2tyAp-eRZs59mguaTc6-x67JUoSxtZ8mOjbRqDuc,5832
|
@@ -507,12 +507,12 @@ reconcile/templates/jira-checkpoint-missinginfo.j2,sha256=c_Vvg-lEENsB3tgxm9B6Y9
|
|
507
507
|
reconcile/templates/rosa-classic-cluster-creation.sh.j2,sha256=M-nzp-GtkQNRe8rdoDAndSKJSJhcJwNFKeql-JP2W7M,2094
|
508
508
|
reconcile/templates/rosa-hcp-cluster-creation.sh.j2,sha256=eeT7xUhmz7Q_HtJOQALF5snZE8cUPGkIh6WUlcBHhhs,2349
|
509
509
|
reconcile/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
510
|
-
reconcile/templating/renderer.py,sha256=
|
510
|
+
reconcile/templating/renderer.py,sha256=YVKhk1piAnk3faT81oeZeMHnFV78Mt-_wgtIC693vtE,14907
|
511
511
|
reconcile/templating/validator.py,sha256=5f9f35PCHOOdjb7KZquL2YdabyuAUokPDa4xutSEHIQ,5360
|
512
512
|
reconcile/templating/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
513
513
|
reconcile/templating/lib/merge_request_manager.py,sha256=XwpOR4rVS9ZiJ_Mn8qfCXPZ7CRLMGSJgeIkqD-8Jhgc,5228
|
514
514
|
reconcile/templating/lib/model.py,sha256=YVUIXuPny3_kpFgBMSud8q_ndY5o882wKiX0l0A14L4,481
|
515
|
-
reconcile/templating/lib/rendering.py,sha256=
|
515
|
+
reconcile/templating/lib/rendering.py,sha256=qjs7WAVSvWH4edbBk6Aaql4ZT_OG9W7L8qi_YeJkHVI,6973
|
516
516
|
reconcile/terraform_init/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
517
517
|
reconcile/terraform_init/integration.py,sha256=pPi4YAjbEE8vDaaRizGf-d-PewqqSJmjcLgAsWFS7G0,6236
|
518
518
|
reconcile/terraform_init/merge_request.py,sha256=3CYtgSd7Q9zjKg4wsDz437EPCRfGeZZ8fZ0Y-ChKXJY,1475
|
@@ -658,7 +658,7 @@ reconcile/utils/sqs_gateway.py,sha256=XNIf3PY4UCPNufP2Ul0UJj3fKlt5larBba-VTT-41F
|
|
658
658
|
reconcile/utils/state.py,sha256=vCHYIfrWLfPyIWEHSaADWlc4OqhwcOiqM3Egqvw-lfo,16372
|
659
659
|
reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
|
660
660
|
reconcile/utils/terraform_client.py,sha256=GoLbfs4d4YItNCeV3NZnrth4sD8ziNYgY2IszruRDpg,37303
|
661
|
-
reconcile/utils/terrascript_aws_client.py,sha256=
|
661
|
+
reconcile/utils/terrascript_aws_client.py,sha256=jVzh5PmphbCAN7Pog_PFYHoHj7lmQGb6Q4FwT_c8pF8,295634
|
662
662
|
reconcile/utils/three_way_diff_strategy.py,sha256=oQcHXd9LVhirJfoaOBoHUYuZVGfyL2voKr6KVI34zZE,4833
|
663
663
|
reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
|
664
664
|
reconcile/utils/vault.py,sha256=6V15LByFghp-U3k0N4lum6V7qt2EAlRfcAxjy5e-FAU,15146
|
@@ -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=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
|
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.dev293.dist-info/METADATA,sha256=1dwm4wJoCGKDdjglqMJw3fdWAvuquaPeE2BIpH7wkUc,24916
|
800
|
+
qontract_reconcile-0.10.2.dev293.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
801
|
+
qontract_reconcile-0.10.2.dev293.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
802
|
+
qontract_reconcile-0.10.2.dev293.dist-info/RECORD,,
|
@@ -6451,6 +6451,18 @@
|
|
6451
6451
|
"isDeprecated": false,
|
6452
6452
|
"deprecationReason": null
|
6453
6453
|
},
|
6454
|
+
{
|
6455
|
+
"name": "externalOrgId",
|
6456
|
+
"description": null,
|
6457
|
+
"args": [],
|
6458
|
+
"type": {
|
6459
|
+
"kind": "SCALAR",
|
6460
|
+
"name": "String",
|
6461
|
+
"ofType": null
|
6462
|
+
},
|
6463
|
+
"isDeprecated": false,
|
6464
|
+
"deprecationReason": null
|
6465
|
+
},
|
6454
6466
|
{
|
6455
6467
|
"name": "environment",
|
6456
6468
|
"description": null,
|
@@ -34178,6 +34190,18 @@
|
|
34178
34190
|
"isDeprecated": false,
|
34179
34191
|
"deprecationReason": null
|
34180
34192
|
},
|
34193
|
+
{
|
34194
|
+
"name": "overwrite",
|
34195
|
+
"description": null,
|
34196
|
+
"args": [],
|
34197
|
+
"type": {
|
34198
|
+
"kind": "SCALAR",
|
34199
|
+
"name": "Boolean",
|
34200
|
+
"ofType": null
|
34201
|
+
},
|
34202
|
+
"isDeprecated": false,
|
34203
|
+
"deprecationReason": null
|
34204
|
+
},
|
34181
34205
|
{
|
34182
34206
|
"name": "patch",
|
34183
34207
|
"description": null,
|
@@ -41014,6 +41038,18 @@
|
|
41014
41038
|
},
|
41015
41039
|
"isDeprecated": false,
|
41016
41040
|
"deprecationReason": null
|
41041
|
+
},
|
41042
|
+
{
|
41043
|
+
"name": "promtool_version",
|
41044
|
+
"description": null,
|
41045
|
+
"args": [],
|
41046
|
+
"type": {
|
41047
|
+
"kind": "SCALAR",
|
41048
|
+
"name": "String",
|
41049
|
+
"ofType": null
|
41050
|
+
},
|
41051
|
+
"isDeprecated": false,
|
41052
|
+
"deprecationReason": null
|
41017
41053
|
}
|
41018
41054
|
],
|
41019
41055
|
"inputFields": null,
|
@@ -40,6 +40,7 @@ query TemplateCollection_v1($name: String) {
|
|
40
40
|
autoApproved
|
41
41
|
condition
|
42
42
|
targetPath
|
43
|
+
overwrite
|
43
44
|
patch {
|
44
45
|
path
|
45
46
|
identifier
|
@@ -92,6 +93,7 @@ class TemplateV1(ConfiguredBaseModel):
|
|
92
93
|
auto_approved: Optional[bool] = Field(..., alias="autoApproved")
|
93
94
|
condition: Optional[str] = Field(..., alias="condition")
|
94
95
|
target_path: str = Field(..., alias="targetPath")
|
96
|
+
overwrite: Optional[bool] = Field(..., alias="overwrite")
|
95
97
|
patch: Optional[TemplatePatchV1] = Field(..., alias="patch")
|
96
98
|
template: str = Field(..., alias="template")
|
97
99
|
template_render_options: Optional[TemplateRenderOptionsV1] = Field(..., alias="templateRenderOptions")
|
@@ -24,6 +24,7 @@ query Templatev1 {
|
|
24
24
|
name
|
25
25
|
autoApproved
|
26
26
|
condition
|
27
|
+
overwrite
|
27
28
|
patch {
|
28
29
|
path
|
29
30
|
identifier
|
@@ -78,6 +79,7 @@ class TemplateV1(ConfiguredBaseModel):
|
|
78
79
|
name: str = Field(..., alias="name")
|
79
80
|
auto_approved: Optional[bool] = Field(..., alias="autoApproved")
|
80
81
|
condition: Optional[str] = Field(..., alias="condition")
|
82
|
+
overwrite: Optional[bool] = Field(..., alias="overwrite")
|
81
83
|
patch: Optional[TemplatePatchV1] = Field(..., alias="patch")
|
82
84
|
target_path: str = Field(..., alias="targetPath")
|
83
85
|
template: str = Field(..., alias="template")
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
from abc import ABC, abstractmethod
|
3
|
+
from functools import cached_property
|
3
4
|
from io import StringIO
|
4
5
|
from typing import Any, Protocol
|
5
6
|
|
@@ -33,6 +34,7 @@ class Template(Protocol):
|
|
33
34
|
condition: str | None
|
34
35
|
target_path: str
|
35
36
|
template: str
|
37
|
+
overwrite: bool | None
|
36
38
|
|
37
39
|
def dict(self) -> dict[str, str]: ...
|
38
40
|
|
@@ -77,14 +79,28 @@ class Renderer(ABC):
|
|
77
79
|
"""
|
78
80
|
pass
|
79
81
|
|
82
|
+
@abstractmethod
|
83
|
+
def target_exist(self) -> bool:
|
84
|
+
"""
|
85
|
+
if target (file or patch block) already exists.
|
86
|
+
"""
|
87
|
+
pass
|
88
|
+
|
80
89
|
def render_target_path(self) -> str:
|
81
90
|
return self._render_template(self.template.target_path).strip()
|
82
91
|
|
83
92
|
def render_condition(self) -> bool:
|
84
|
-
|
93
|
+
if self._render_template(self.template.condition or "True") != "True":
|
94
|
+
return False
|
95
|
+
if self.template.overwrite:
|
96
|
+
return True
|
97
|
+
return not self.target_exist()
|
85
98
|
|
86
99
|
|
87
100
|
class FullRenderer(Renderer):
|
101
|
+
def target_exist(self) -> bool:
|
102
|
+
return self.data.current is not None
|
103
|
+
|
88
104
|
def render_output(self) -> str:
|
89
105
|
"""
|
90
106
|
Take the variables from Template Data and render the template with it.
|
@@ -95,6 +111,12 @@ class FullRenderer(Renderer):
|
|
95
111
|
|
96
112
|
|
97
113
|
class PatchRenderer(Renderer):
|
114
|
+
def target_exist(self) -> bool:
|
115
|
+
if isinstance(self._matched_value, list):
|
116
|
+
dta_identifier = self._get_identifier(self._data_to_add)
|
117
|
+
return self._find_index(self._matched_value, dta_identifier) is not None
|
118
|
+
return True
|
119
|
+
|
98
120
|
def render_output(self) -> str:
|
99
121
|
"""
|
100
122
|
Takes the variables from Template Data and render the template with it.
|
@@ -105,70 +127,69 @@ class PatchRenderer(Renderer):
|
|
105
127
|
|
106
128
|
This method returns the entire file as a string.
|
107
129
|
"""
|
108
|
-
if self.
|
109
|
-
|
110
|
-
|
111
|
-
p = parse_jsonpath(self._render_template(self.template.patch.path))
|
112
|
-
|
113
|
-
matched_values = [match.value for match in p.find(self.data.current)]
|
114
|
-
|
115
|
-
if len(matched_values) != 1:
|
116
|
-
raise ValueError(
|
117
|
-
f"Expected exactly one match for {self.template.patch.path}, got {len(matched_values)}"
|
118
|
-
)
|
119
|
-
matched_value = matched_values[0]
|
120
|
-
|
121
|
-
data_to_add = self.ruamel_instance.load(
|
122
|
-
self._render_template(self.template.template)
|
123
|
-
)
|
124
|
-
|
125
|
-
if isinstance(matched_value, list):
|
126
|
-
|
127
|
-
def get_identifier(data: dict[str, Any]) -> Any:
|
128
|
-
assert self.template.patch is not None # mypy
|
129
|
-
if not self.template.patch.identifier:
|
130
|
-
raise ValueError(
|
131
|
-
f"Expected identifier in patch for list at {self.template}"
|
132
|
-
)
|
133
|
-
if self.template.patch.identifier.startswith(
|
134
|
-
"$"
|
135
|
-
) and not self.template.patch.identifier.startswith("$ref"):
|
136
|
-
# jsonpath and list of strings support
|
137
|
-
if matches := [
|
138
|
-
match.value
|
139
|
-
for match in parse_jsonpath(
|
140
|
-
self.template.patch.identifier
|
141
|
-
).find(data)
|
142
|
-
]:
|
143
|
-
return matches[0]
|
144
|
-
return None
|
145
|
-
return data.get(self.template.patch.identifier)
|
146
|
-
|
147
|
-
dta_identifier = get_identifier(data_to_add)
|
130
|
+
if isinstance(self._matched_value, list):
|
131
|
+
dta_identifier = self._get_identifier(self._data_to_add)
|
148
132
|
if not dta_identifier:
|
133
|
+
assert self.template.patch is not None # mypy
|
149
134
|
raise ValueError(
|
150
135
|
f"Expected identifier {self.template.patch.identifier} in data to add"
|
151
136
|
)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
for index, data in enumerate(matched_value)
|
157
|
-
if get_identifier(data) == dta_identifier
|
158
|
-
),
|
159
|
-
None,
|
160
|
-
)
|
161
|
-
if index is None:
|
162
|
-
matched_value.append(data_to_add)
|
137
|
+
if (
|
138
|
+
index := self._find_index(self._matched_value, dta_identifier)
|
139
|
+
) is not None:
|
140
|
+
self._matched_value[index] = self._data_to_add
|
163
141
|
else:
|
164
|
-
|
142
|
+
self._matched_value.append(self._data_to_add)
|
165
143
|
else:
|
166
|
-
|
144
|
+
self._matched_value.update(self._data_to_add)
|
167
145
|
|
168
146
|
with StringIO() as s:
|
169
147
|
self.ruamel_instance.dump(self.data.current, s)
|
170
148
|
return s.getvalue()
|
171
149
|
|
150
|
+
@cached_property
|
151
|
+
def _matched_value(self) -> Any:
|
152
|
+
assert self.template.patch is not None # mypy
|
153
|
+
p = parse_jsonpath(self._render_template(self.template.patch.path))
|
154
|
+
matched_values = [match.value for match in p.find(self.data.current)]
|
155
|
+
if len(matched_values) != 1:
|
156
|
+
raise ValueError(
|
157
|
+
f"Expected exactly one match for {self.template.patch.path}, got {len(matched_values)}"
|
158
|
+
)
|
159
|
+
return matched_values[0]
|
160
|
+
|
161
|
+
@cached_property
|
162
|
+
def _data_to_add(self) -> Any:
|
163
|
+
return self.ruamel_instance.load(self._render_template(self.template.template))
|
164
|
+
|
165
|
+
def _get_identifier(self, data: dict[str, Any]) -> Any:
|
166
|
+
assert self.template.patch is not None # mypy
|
167
|
+
if not self.template.patch.identifier:
|
168
|
+
raise ValueError(
|
169
|
+
f"Expected identifier in patch for list at {self.template}"
|
170
|
+
)
|
171
|
+
if self.template.patch.identifier.startswith(
|
172
|
+
"$"
|
173
|
+
) and not self.template.patch.identifier.startswith("$ref"):
|
174
|
+
# jsonpath and list of strings support
|
175
|
+
if matches := [
|
176
|
+
match.value
|
177
|
+
for match in parse_jsonpath(self.template.patch.identifier).find(data)
|
178
|
+
]:
|
179
|
+
return matches[0]
|
180
|
+
return None
|
181
|
+
return data.get(self.template.patch.identifier)
|
182
|
+
|
183
|
+
def _find_index(
|
184
|
+
self,
|
185
|
+
matched_value: list,
|
186
|
+
dta_identifier: Any,
|
187
|
+
) -> int | None:
|
188
|
+
for index, data in enumerate(matched_value):
|
189
|
+
if self._get_identifier(data) == dta_identifier:
|
190
|
+
return index
|
191
|
+
return None
|
192
|
+
|
172
193
|
|
173
194
|
def create_renderer(
|
174
195
|
template: Template,
|
reconcile/templating/renderer.py
CHANGED
@@ -104,14 +104,17 @@ class LocalFilePersistence(FilePersistence):
|
|
104
104
|
def read(self, path: str) -> str | None:
|
105
105
|
return self._read_local_file(join_path(self.app_interface_data_path, path))
|
106
106
|
|
107
|
-
def
|
108
|
-
if self.dry_run:
|
109
|
-
return
|
107
|
+
def flush(self) -> None:
|
110
108
|
for output in self.outputs:
|
111
109
|
filepath = Path(join_path(self.app_interface_data_path, output.path))
|
112
110
|
filepath.parent.mkdir(parents=True, exist_ok=True)
|
113
111
|
filepath.write_text(output.content, encoding="utf-8")
|
114
112
|
|
113
|
+
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
114
|
+
if self.dry_run:
|
115
|
+
return
|
116
|
+
self.flush()
|
117
|
+
|
115
118
|
|
116
119
|
class PersistenceTransaction(FilePersistence):
|
117
120
|
"""
|
@@ -190,13 +190,14 @@ from reconcile.utils.terraform import safe_resource_id
|
|
190
190
|
from reconcile.utils.vcs import VCS
|
191
191
|
|
192
192
|
GH_BASE_URL = os.environ.get("GITHUB_API", "https://api.github.com")
|
193
|
-
|
194
|
-
|
193
|
+
ROSA_AUTH_LOGTOES_RELEASE = "repos/app-sre/logs-to-elasticsearch-lambda/releases/latest"
|
194
|
+
ROSA_AUTH_KINESIS_TO_OS_RELEASE = (
|
195
195
|
"https://github.com/app-sre/kinesis-to-opensearch-lambda/releases/latest"
|
196
196
|
)
|
197
|
-
|
197
|
+
ROSA_AUTH_PRE_SIGNUP_RELEASE = (
|
198
198
|
"repos/app-sre/cognito-pre-signup-trigger/releases/latest"
|
199
199
|
)
|
200
|
+
ROSA_AUTH_PRE_TOKEN_RELEASE = "repos/app-sre/cognito-pre-token-trigger/releases/latest"
|
200
201
|
# VARIABLE_KEYS are passed to common_values on instantiation of a provider
|
201
202
|
VARIABLE_KEYS = [
|
202
203
|
"region",
|
@@ -546,12 +547,14 @@ class TerrascriptClient:
|
|
546
547
|
self.partitions = {
|
547
548
|
a["name"]: a.get("partition") or "aws" for a in filtered_accounts
|
548
549
|
}
|
549
|
-
self.
|
550
|
-
self.
|
551
|
-
self.
|
552
|
-
self.
|
553
|
-
self.
|
554
|
-
self.
|
550
|
+
self.rosa_auth_logtoes_zip = ""
|
551
|
+
self.rosa_auth_logtoes_zip_lock = Lock()
|
552
|
+
self.rosa_auth_pre_signup_zip = ""
|
553
|
+
self.rosa_auth_pre_signup_zip_lock = Lock()
|
554
|
+
self.rosa_auth_pre_token_zip = ""
|
555
|
+
self.rosa_auth_pre_token_zip_lock = Lock()
|
556
|
+
self.rosa_auth_kinesis_to_os_zip: dict[str, str] = {}
|
557
|
+
self.rosa_auth_kinesis_to_os_zip_lock = Lock()
|
555
558
|
self.github: Github | None = None
|
556
559
|
self.github_lock = Lock()
|
557
560
|
self.gitlab: GitLabApi | None = None
|
@@ -608,15 +611,17 @@ class TerrascriptClient:
|
|
608
611
|
)
|
609
612
|
raise ValueError(f"No bucket config found for account {account_name}")
|
610
613
|
|
611
|
-
def
|
612
|
-
if not self.
|
613
|
-
with self.
|
614
|
+
def get_rosa_auth_kinesis_to_os_zip(self, release_url: str) -> str:
|
615
|
+
if not self.rosa_auth_kinesis_to_os_zip.get(release_url):
|
616
|
+
with self.rosa_auth_kinesis_to_os_zip_lock:
|
614
617
|
# this may have already happened, so we check again
|
615
|
-
if not self.
|
616
|
-
self.
|
617
|
-
|
618
|
+
if not self.rosa_auth_kinesis_to_os_zip.get(release_url):
|
619
|
+
self.rosa_auth_kinesis_to_os_zip[release_url] = (
|
620
|
+
self.download_rosa_auth_kinesis_to_os_zip(release_url)
|
621
|
+
)
|
622
|
+
return self.rosa_auth_kinesis_to_os_zip[release_url]
|
618
623
|
|
619
|
-
def
|
624
|
+
def download_rosa_auth_kinesis_to_os_zip(self, release_url: str) -> str:
|
620
625
|
github = self.init_github()
|
621
626
|
url = release_url.replace("https://", "").split("/")
|
622
627
|
repo_name = f"{url[1]}/{url[2]}"
|
@@ -639,14 +644,16 @@ class TerrascriptClient:
|
|
639
644
|
return zip_file
|
640
645
|
|
641
646
|
def get_logtoes_zip(self, release_url):
|
642
|
-
if not self.
|
643
|
-
with self.
|
647
|
+
if not self.rosa_auth_logtoes_zip:
|
648
|
+
with self.rosa_auth_logtoes_zip_lock:
|
644
649
|
# this may have already happened, so we check again
|
645
|
-
if not self.
|
650
|
+
if not self.rosa_auth_logtoes_zip:
|
646
651
|
self.token = get_default_config()["token"]
|
647
|
-
self.
|
648
|
-
|
649
|
-
|
652
|
+
self.rosa_auth_logtoes_zip = self.download_logtoes_zip(
|
653
|
+
ROSA_AUTH_LOGTOES_RELEASE
|
654
|
+
)
|
655
|
+
if release_url == ROSA_AUTH_LOGTOES_RELEASE:
|
656
|
+
return self.rosa_auth_logtoes_zip
|
650
657
|
return self.download_logtoes_zip(release_url)
|
651
658
|
|
652
659
|
def download_logtoes_zip(self, release_url):
|
@@ -663,28 +670,57 @@ class TerrascriptClient:
|
|
663
670
|
f.write(r.content)
|
664
671
|
return zip_file
|
665
672
|
|
666
|
-
def
|
667
|
-
if not self.
|
668
|
-
with self.
|
673
|
+
def get_rosa_auth_pre_signup_zip(self, release_url):
|
674
|
+
if not self.rosa_auth_pre_signup_zip:
|
675
|
+
with self.rosa_auth_pre_signup_zip_lock:
|
669
676
|
# this may have already happened, so we check again
|
670
|
-
if not self.
|
677
|
+
if not self.rosa_auth_pre_signup_zip:
|
671
678
|
self.token = get_default_config()["token"]
|
672
|
-
self.
|
673
|
-
self.
|
674
|
-
|
679
|
+
self.rosa_auth_pre_signup_zip = (
|
680
|
+
self.download_rosa_auth_pre_signup_zip(
|
681
|
+
ROSA_AUTH_PRE_SIGNUP_RELEASE
|
675
682
|
)
|
676
683
|
)
|
677
|
-
if release_url ==
|
678
|
-
return self.
|
679
|
-
return self.
|
684
|
+
if release_url == ROSA_AUTH_PRE_SIGNUP_RELEASE:
|
685
|
+
return self.rosa_auth_pre_signup_zip
|
686
|
+
return self.download_rosa_auth_pre_signup_zip(release_url)
|
680
687
|
|
681
|
-
def
|
688
|
+
def download_rosa_auth_pre_signup_zip(self, release_url):
|
682
689
|
headers = {"Authorization": "token " + self.token}
|
683
690
|
r = requests.get(GH_BASE_URL + "/" + release_url, headers=headers, timeout=60)
|
684
691
|
r.raise_for_status()
|
685
692
|
data = r.json()
|
686
693
|
zip_url = data["assets"][0]["browser_download_url"]
|
687
|
-
zip_file = "/tmp/
|
694
|
+
zip_file = "/tmp/RosaAuthPreSignUp-" + data["tag_name"] + ".zip"
|
695
|
+
if not os.path.exists(zip_file):
|
696
|
+
r = requests.get(zip_url, timeout=60)
|
697
|
+
r.raise_for_status()
|
698
|
+
with open(zip_file, "wb") as f:
|
699
|
+
f.write(r.content)
|
700
|
+
return zip_file
|
701
|
+
|
702
|
+
def get_rosa_auth_pre_token_zip(self, release_url):
|
703
|
+
if not self.rosa_auth_pre_token_zip:
|
704
|
+
with self.rosa_auth_pre_token_zip_lock:
|
705
|
+
# this may have already happened, so we check again
|
706
|
+
if not self.rosa_auth_pre_token_zip:
|
707
|
+
self.token = get_default_config()["token"]
|
708
|
+
self.rosa_auth_pre_token_zip = (
|
709
|
+
self.download_rosa_auth_pre_token_zip(
|
710
|
+
ROSA_AUTH_PRE_TOKEN_RELEASE
|
711
|
+
)
|
712
|
+
)
|
713
|
+
if release_url == ROSA_AUTH_PRE_TOKEN_RELEASE:
|
714
|
+
return self.rosa_auth_pre_token_zip
|
715
|
+
return self.download_rosa_auth_pre_token_zip(release_url)
|
716
|
+
|
717
|
+
def download_rosa_auth_pre_token_zip(self, release_url):
|
718
|
+
headers = {"Authorization": "token " + self.token}
|
719
|
+
r = requests.get(GH_BASE_URL + "/" + release_url, headers=headers, timeout=60)
|
720
|
+
r.raise_for_status()
|
721
|
+
data = r.json()
|
722
|
+
zip_url = data["assets"][0]["browser_download_url"]
|
723
|
+
zip_file = "/tmp/RosaAuthPreToken-" + data["tag_name"] + ".zip"
|
688
724
|
if not os.path.exists(zip_file):
|
689
725
|
r = requests.get(zip_url, timeout=60)
|
690
726
|
r.raise_for_status()
|
@@ -3697,7 +3733,7 @@ class TerrascriptClient:
|
|
3697
3733
|
data.aws_elasticsearch_domain(es_identifier, **es_domain)
|
3698
3734
|
)
|
3699
3735
|
|
3700
|
-
release_url = common_values.get("release_url",
|
3736
|
+
release_url = common_values.get("release_url", ROSA_AUTH_LOGTOES_RELEASE)
|
3701
3737
|
zip_file = self.get_logtoes_zip(release_url)
|
3702
3738
|
|
3703
3739
|
lambda_identifier = f"{identifier}-lambda"
|
@@ -4007,8 +4043,10 @@ class TerrascriptClient:
|
|
4007
4043
|
data.aws_elasticsearch_domain(es_identifier, **es_domain)
|
4008
4044
|
)
|
4009
4045
|
|
4010
|
-
release_url = common_values.get(
|
4011
|
-
|
4046
|
+
release_url = common_values.get(
|
4047
|
+
"release_url", ROSA_AUTH_KINESIS_TO_OS_RELEASE
|
4048
|
+
)
|
4049
|
+
zip_file = self.get_rosa_auth_kinesis_to_os_zip(release_url)
|
4012
4050
|
|
4013
4051
|
lambda_identifier = f"{identifier}-lambda"
|
4014
4052
|
lambda_values = {
|
@@ -5983,16 +6021,14 @@ class TerrascriptClient:
|
|
5983
6021
|
tf_resources.append(lambda_iam_role_resource)
|
5984
6022
|
|
5985
6023
|
# Setup + manage Lambda resources
|
5986
|
-
# pre-signup lambda
|
5987
|
-
release_url = common_values.get(
|
5988
|
-
"release_url", ROSA_AUTHENTICATOR_PRE_SIGNUP_RELEASE
|
5989
|
-
)
|
5990
|
-
zip_file = self.get_rosa_authenticator_zip(release_url)
|
5991
6024
|
|
6025
|
+
# pre-signup lambda
|
6026
|
+
release_url = common_values.get("release_url", ROSA_AUTH_PRE_SIGNUP_RELEASE)
|
6027
|
+
zip_file = self.get_rosa_auth_pre_signup_zip(release_url)
|
5992
6028
|
cognito_pre_signup_lambda_resource = aws_lambda_function(
|
5993
6029
|
"cognito_pre_signup",
|
5994
6030
|
function_name=f"ocm-{identifier}-cognito-pre-signup",
|
5995
|
-
runtime="
|
6031
|
+
runtime="nodejs18.x",
|
5996
6032
|
role=f"${{{lambda_iam_role_resource.arn}}}",
|
5997
6033
|
handler="index.handler",
|
5998
6034
|
filename=zip_file,
|
@@ -6001,6 +6037,21 @@ class TerrascriptClient:
|
|
6001
6037
|
)
|
6002
6038
|
tf_resources.append(cognito_pre_signup_lambda_resource)
|
6003
6039
|
|
6040
|
+
# pre-token lambda
|
6041
|
+
release_url = common_values.get("release_url", ROSA_AUTH_PRE_TOKEN_RELEASE)
|
6042
|
+
zip_file = self.get_rosa_auth_pre_token_zip(release_url)
|
6043
|
+
cognito_pre_token_lambda_resource = aws_lambda_function(
|
6044
|
+
"cognito_pre_token",
|
6045
|
+
function_name=f"ocm-{identifier}-cognito-pre-token",
|
6046
|
+
runtime="nodejs18.x",
|
6047
|
+
role=f"${{{lambda_iam_role_resource.arn}}}",
|
6048
|
+
handler="index.handler",
|
6049
|
+
filename=zip_file,
|
6050
|
+
source_code_hash='${filebase64sha256("' + zip_file + '")}',
|
6051
|
+
tracing_config={"mode": "PassThrough"},
|
6052
|
+
)
|
6053
|
+
tf_resources.append(cognito_pre_token_lambda_resource)
|
6054
|
+
|
6004
6055
|
# setup s3_client
|
6005
6056
|
# pattern followed from utils/state.py
|
6006
6057
|
# The variable "account" is the name of the AWS account we are reconciling
|
@@ -6084,7 +6135,8 @@ class TerrascriptClient:
|
|
6084
6135
|
"pool",
|
6085
6136
|
name=f"ocm-{identifier}-pool",
|
6086
6137
|
lambda_config={
|
6087
|
-
"pre_sign_up": f"${{{cognito_pre_signup_lambda_resource.arn}}}"
|
6138
|
+
"pre_sign_up": f"${{{cognito_pre_signup_lambda_resource.arn}}}",
|
6139
|
+
"pre_token_generation": f"${{{cognito_pre_token_lambda_resource.arn}}}",
|
6088
6140
|
},
|
6089
6141
|
**pool_args,
|
6090
6142
|
)
|
@@ -6100,6 +6152,16 @@ class TerrascriptClient:
|
|
6100
6152
|
)
|
6101
6153
|
tf_resources.append(cognito_pre_signup_lambda_permission_resource)
|
6102
6154
|
|
6155
|
+
# Finish up lambda - pre token
|
6156
|
+
cognito_pre_token_lambda_permission_resource = aws_lambda_permission(
|
6157
|
+
"cognito_pre_token_permission",
|
6158
|
+
action="lambda:InvokeFunction",
|
6159
|
+
function_name=cognito_pre_token_lambda_resource.function_name,
|
6160
|
+
source_arn=f"${{{cognito_user_pool_resource.arn}}}",
|
6161
|
+
principal="cognito-idp.amazonaws.com",
|
6162
|
+
)
|
6163
|
+
tf_resources.append(cognito_pre_token_lambda_permission_resource)
|
6164
|
+
|
6103
6165
|
# POOL DOMAIN
|
6104
6166
|
cognito_user_pool_domain_resource = aws_cognito_user_pool_domain(
|
6105
6167
|
"userpool_domain",
|
@@ -6582,7 +6644,7 @@ class TerrascriptClient:
|
|
6582
6644
|
response_parameters={
|
6583
6645
|
"method.response.header.Location": f"'{user_pool_url}/oauth2/authorize?client_id="
|
6584
6646
|
f"${{{cognito_user_pool_client.id}}}\u0026response_type=code"
|
6585
|
-
f"\u0026scope=openid+gateway/AccessToken\u0026redirect_uri={bucket_url}/"
|
6647
|
+
f"\u0026scope=email+openid+gateway/AccessToken\u0026redirect_uri={bucket_url}/"
|
6586
6648
|
"token.html'",
|
6587
6649
|
},
|
6588
6650
|
depends_on=["aws_api_gateway_integration.gw_integration_auth"],
|
{qontract_reconcile-0.10.2.dev291.dist-info → qontract_reconcile-0.10.2.dev293.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|