qontract-reconcile 0.10.1rc354__py3-none-any.whl → 0.10.1rc355__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.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/RECORD +8 -8
- reconcile/openshift_saas_deploy.py +7 -5
- reconcile/openshift_saas_deploy_change_tester.py +7 -7
- reconcile/typed_queries/saas_files.py +159 -118
- {qontract_reconcile-0.10.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc355
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Home-page: https://github.com/app-sre/qontract-reconcile
|
6
6
|
Author: Red Hat App-SRE Team
|
{qontract_reconcile-0.10.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/RECORD
RENAMED
@@ -69,8 +69,8 @@ reconcile/openshift_resources.py,sha256=kwsY5cko7udEKNlhL2oKiKv_5wzEw9wmmwROE016
|
|
69
69
|
reconcile/openshift_resources_base.py,sha256=K56KXgxxnAsVRvqSMVTW47_ebCsxYSc0BsViwZcRS6k,44409
|
70
70
|
reconcile/openshift_rolebindings.py,sha256=1k0o3hb3ZhhlbUjc8cP7IjKFux0oZApT8kLT8Y-pvqI,6579
|
71
71
|
reconcile/openshift_routes.py,sha256=fXvuPSjcjVw1X3j2EQvUAdbOepmIFdKk-M3qP8QzPiw,1075
|
72
|
-
reconcile/openshift_saas_deploy.py,sha256=
|
73
|
-
reconcile/openshift_saas_deploy_change_tester.py,sha256=
|
72
|
+
reconcile/openshift_saas_deploy.py,sha256=In3hQfSCni3T5P1vP_j3bzEO2thLoQuxz4HrMSPjyIc,10761
|
73
|
+
reconcile/openshift_saas_deploy_change_tester.py,sha256=spWjxapC-u4TrCAsz1Q6_297QwfrIRx19oqz2bRPQn0,8907
|
74
74
|
reconcile/openshift_saas_deploy_trigger_base.py,sha256=UEKWAJo6cN3Nml89tzJzbnpkJ7efOnFDf9Wfz9_tBdg,14325
|
75
75
|
reconcile/openshift_saas_deploy_trigger_cleaner.py,sha256=tcvziJdw5lgJbbogk0-wKT2aYCFP99sL4qTSfau4otY,2971
|
76
76
|
reconcile/openshift_saas_deploy_trigger_configs.py,sha256=uWzUV5D5CW0frdi1ys7BObNg-rA-VZKlefd4TD_Z-pY,959
|
@@ -456,7 +456,7 @@ reconcile/typed_queries/namespaces.py,sha256=vItPrn7sfcHOix-VvkzQkf54_ljzI_ymyxh
|
|
456
456
|
reconcile/typed_queries/namespaces_minimal.py,sha256=rUtqNQ0ORXXUTQfnpsMURymAJ4gYtE77V-Lb3LiJFEY,278
|
457
457
|
reconcile/typed_queries/pagerduty_instances.py,sha256=QCHqEAakiH6eSob0Pnnn3IBd8Ga0zpEp1Z6Qu3v2uH4,733
|
458
458
|
reconcile/typed_queries/repos.py,sha256=RKBsf7IDS6NsXTtXxJ9Ol9G3bxG9sr3vW9QQ2bahEHo,512
|
459
|
-
reconcile/typed_queries/saas_files.py,sha256=
|
459
|
+
reconcile/typed_queries/saas_files.py,sha256=BuDZf83hv6ItJMqBEWBOF14XNyeEwr4qMkEWsA1fTK8,13990
|
460
460
|
reconcile/typed_queries/smtp.py,sha256=aSLglYa5bHKmlGwKkxq2RZqyMWuAf0a4S_mOuhDa084,542
|
461
461
|
reconcile/typed_queries/status_board.py,sha256=jsisR46kuHJM0VOPRQinnZigFNo51lHyvy-Q6Fdhs94,1673
|
462
462
|
reconcile/typed_queries/tekton_pipeline_providers.py,sha256=2mpHBdsNPQB94tw0H9aenGuqj8EEjYolQ03YEq1CpiY,546
|
@@ -607,8 +607,8 @@ tools/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
607
607
|
tools/test/test_qontract_cli.py,sha256=awwTHEc2DWlykuqGIYM0WOBoSL0KRnOraCLk3C7izis,1401
|
608
608
|
tools/test/test_sd_app_sre_alert_report.py,sha256=JeLhgzpKCPgLvptwg_4ZvJHLVWKNG1T5845HXTkMBxA,1826
|
609
609
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
610
|
-
qontract_reconcile-0.10.
|
611
|
-
qontract_reconcile-0.10.
|
612
|
-
qontract_reconcile-0.10.
|
613
|
-
qontract_reconcile-0.10.
|
614
|
-
qontract_reconcile-0.10.
|
610
|
+
qontract_reconcile-0.10.1rc355.dist-info/METADATA,sha256=OpYBE-4PcUg9vnQAfecLU0U3GXQITpJb672__LKMp4Q,2347
|
611
|
+
qontract_reconcile-0.10.1rc355.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
612
|
+
qontract_reconcile-0.10.1rc355.dist-info/entry_points.txt,sha256=ErVY2Jp-0Rtuq5KOtMlW5yvna4nIEuc_1YbEdEdcy9o,301
|
613
|
+
qontract_reconcile-0.10.1rc355.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
614
|
+
qontract_reconcile-0.10.1rc355.dist-info/RECORD,,
|
@@ -20,7 +20,7 @@ from reconcile.typed_queries.app_interface_vault_settings import (
|
|
20
20
|
)
|
21
21
|
from reconcile.typed_queries.saas_files import (
|
22
22
|
SaasFile,
|
23
|
-
|
23
|
+
SaasFileList,
|
24
24
|
get_saasherder_settings,
|
25
25
|
)
|
26
26
|
from reconcile.utils.defer import defer
|
@@ -100,15 +100,17 @@ def run(
|
|
100
100
|
env_name: Optional[str] = None,
|
101
101
|
trigger_integration: Optional[str] = None,
|
102
102
|
trigger_reason: Optional[str] = None,
|
103
|
-
|
103
|
+
saas_file_list: Optional[SaasFileList] = None,
|
104
104
|
defer: Optional[Callable] = None,
|
105
105
|
) -> None:
|
106
106
|
vault_settings = get_app_interface_vault_settings()
|
107
107
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
108
108
|
|
109
|
-
if not
|
110
|
-
|
111
|
-
|
109
|
+
if not saas_file_list:
|
110
|
+
saas_file_list = SaasFileList()
|
111
|
+
all_saas_files = saas_file_list.saas_files
|
112
|
+
saas_files = saas_file_list.where(name=saas_file_name, env_name=env_name)
|
113
|
+
|
112
114
|
if not saas_files:
|
113
115
|
logging.error("no saas files found")
|
114
116
|
raise RuntimeError("no saas files found")
|
@@ -18,7 +18,7 @@ from reconcile.gql_definitions.common.saas_files import (
|
|
18
18
|
from reconcile.gql_definitions.fragments.vault_secret import VaultSecret
|
19
19
|
from reconcile.typed_queries.saas_files import (
|
20
20
|
SaasFile,
|
21
|
-
|
21
|
+
SaasFileList,
|
22
22
|
)
|
23
23
|
from reconcile.utils import gql
|
24
24
|
from reconcile.utils.gitlab_api import GitLabApi
|
@@ -58,7 +58,7 @@ def osd_run_wrapper(
|
|
58
58
|
dry_run: bool,
|
59
59
|
available_thread_pool_size: int,
|
60
60
|
use_jump_host: bool,
|
61
|
-
|
61
|
+
saas_file_list: Optional[SaasFileList],
|
62
62
|
) -> int:
|
63
63
|
saas_file_name, env_name = spec
|
64
64
|
exit_code = 0
|
@@ -69,7 +69,7 @@ def osd_run_wrapper(
|
|
69
69
|
use_jump_host=use_jump_host,
|
70
70
|
saas_file_name=saas_file_name,
|
71
71
|
env_name=env_name,
|
72
|
-
|
72
|
+
saas_file_list=saas_file_list,
|
73
73
|
)
|
74
74
|
except SystemExit as e:
|
75
75
|
exit_code = e.code if isinstance(e.code, int) else 1
|
@@ -214,10 +214,10 @@ def run(
|
|
214
214
|
)
|
215
215
|
# find the differences in saas-file state
|
216
216
|
comparison_saas_file_state = collect_state(
|
217
|
-
|
217
|
+
SaasFileList(query_func=comparison_gql_api.query).saas_files
|
218
218
|
)
|
219
|
-
|
220
|
-
desired_saas_file_state = collect_state(
|
219
|
+
saas_file_list = SaasFileList()
|
220
|
+
desired_saas_file_state = collect_state(saas_file_list.saas_files)
|
221
221
|
# compare dicts against dicts which is much faster than comparing BaseModel objects
|
222
222
|
comparison_saas_file_state_dicts = [s.dict() for s in comparison_saas_file_state]
|
223
223
|
saas_file_state_diffs = [
|
@@ -249,7 +249,7 @@ def run(
|
|
249
249
|
dry_run=dry_run,
|
250
250
|
available_thread_pool_size=available_thread_pool_size,
|
251
251
|
use_jump_host=use_jump_host,
|
252
|
-
|
252
|
+
saas_file_list=saas_file_list,
|
253
253
|
)
|
254
254
|
|
255
255
|
if [ec for ec in exit_codes if ec]:
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import hashlib
|
2
2
|
import json
|
3
3
|
from collections.abc import Callable
|
4
|
+
from threading import Lock
|
4
5
|
from typing import (
|
5
6
|
Any,
|
6
7
|
Optional,
|
@@ -8,7 +9,6 @@ from typing import (
|
|
8
9
|
)
|
9
10
|
|
10
11
|
from jsonpath_ng.exceptions import JsonPathParserError
|
11
|
-
from jsonpath_ng.ext import parser
|
12
12
|
from pydantic import (
|
13
13
|
BaseModel,
|
14
14
|
Extra,
|
@@ -51,6 +51,7 @@ from reconcile.utils.exceptions import (
|
|
51
51
|
AppInterfaceSettingsError,
|
52
52
|
ParameterError,
|
53
53
|
)
|
54
|
+
from reconcile.utils.jsonpath import parse_jsonpath
|
54
55
|
|
55
56
|
|
56
57
|
class SaasResourceTemplateTarget(ConfiguredBaseModel):
|
@@ -141,51 +142,164 @@ class SaasFile(ConfiguredBaseModel):
|
|
141
142
|
self_service_roles: Optional[list[RoleV1]] = Field(..., alias="selfServiceRoles")
|
142
143
|
|
143
144
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
145
|
+
class SaasFileList:
|
146
|
+
def __init__(
|
147
|
+
self,
|
148
|
+
name: Optional[str] = None,
|
149
|
+
query_func: Optional[Callable] = None,
|
150
|
+
namespaces: Optional[list[SaasTargetNamespace]] = None,
|
151
|
+
) -> None:
|
152
|
+
# query_func and namespaces are optional args mostly used in tests
|
153
|
+
if not query_func:
|
154
|
+
query_func = gql.get_api().query
|
155
|
+
if not namespaces:
|
156
|
+
namespaces = namespaces_query(query_func).namespaces or []
|
157
|
+
self.namespaces = namespaces
|
158
|
+
self.cluster_namespaces = {
|
159
|
+
(ns.cluster.name, ns.name): ns for ns in self.namespaces
|
160
|
+
}
|
161
|
+
|
162
|
+
self._init_caches()
|
163
|
+
|
164
|
+
self.saas_files_v2 = saas_files_query(query_func).saas_files or []
|
165
|
+
if name:
|
166
|
+
self.saas_files_v2 = [sf for sf in self.saas_files_v2 if sf.name == name]
|
167
|
+
self.saas_files = self._resolve_namespace_selectors()
|
168
|
+
|
169
|
+
def _init_caches(self) -> None:
|
170
|
+
self._namespaces_as_dict_cache: Optional[dict[str, list[Any]]] = None
|
171
|
+
self._namespaces_as_dict_lock = Lock()
|
172
|
+
self._matching_namespaces_cache: dict[str, Any] = {}
|
173
|
+
self._matching_namespaces_lock = Lock()
|
174
|
+
|
175
|
+
def _resolve_namespace_selectors(self) -> list[SaasFile]:
|
176
|
+
saas_files: list[SaasFile] = []
|
177
|
+
# resolve namespaceSelectors to real namespaces
|
178
|
+
for sfv2 in self.saas_files_v2:
|
179
|
+
for rt_gql in sfv2.resource_templates:
|
180
|
+
for target_gql in rt_gql.targets[:]:
|
181
|
+
# either namespace or namespaceSelector must be set
|
182
|
+
if target_gql.namespace and target_gql.namespace_selector:
|
183
|
+
raise ParameterError(
|
184
|
+
f"SaasFile {sfv2.name}: namespace and namespaceSelector are mutually exclusive"
|
185
|
+
)
|
186
|
+
if not target_gql.provider:
|
187
|
+
target_gql.provider = "static"
|
188
|
+
|
189
|
+
if (
|
190
|
+
target_gql.namespace_selector
|
191
|
+
and target_gql.provider != "dynamic"
|
192
|
+
):
|
193
|
+
raise ParameterError(
|
194
|
+
f"SaasFile {sfv2.name}: namespaceSelector can only be used with 'provider: dynamic'"
|
195
|
+
)
|
196
|
+
if (
|
197
|
+
target_gql.namespace_selector
|
198
|
+
and target_gql.provider == "dynamic"
|
199
|
+
):
|
200
|
+
rt_gql.targets.remove(target_gql)
|
201
|
+
rt_gql.targets += self.create_targets_for_namespace_selector(
|
202
|
+
target_gql, target_gql.namespace_selector
|
203
|
+
)
|
204
|
+
# convert SaasFileV2 (with optional resource_templates.targets.namespace field)
|
205
|
+
# to SaasFile (with required resource_templates.targets.namespace field)
|
206
|
+
saas_files.append(SaasFile(**export_model(sfv2)))
|
207
|
+
return saas_files
|
208
|
+
|
209
|
+
def create_targets_for_namespace_selector(
|
210
|
+
self,
|
211
|
+
target: SaasResourceTemplateTargetV2,
|
212
|
+
namespace_selector: SaasResourceTemplateTargetNamespaceSelectorV1,
|
213
|
+
) -> list[SaasResourceTemplateTargetV2]:
|
214
|
+
targets = []
|
215
|
+
for namespace in self.get_namespaces_by_selector(namespace_selector):
|
216
|
+
target_dict = export_model(target)
|
217
|
+
target_dict["namespace"] = export_model(namespace)
|
218
|
+
targets.append(SaasResourceTemplateTargetV2(**target_dict))
|
219
|
+
return targets
|
220
|
+
|
221
|
+
def _get_namespaces_as_dict(self) -> dict[str, list[Any]]:
|
222
|
+
# json representation of all the namespaces to filter on
|
223
|
+
# remove all the None values to simplify the jsonpath expressions
|
224
|
+
if self._namespaces_as_dict_cache is None:
|
225
|
+
with self._namespaces_as_dict_lock:
|
226
|
+
self._namespaces_as_dict_cache = {
|
227
|
+
"namespace": [
|
228
|
+
ns.dict(by_alias=True, exclude_none=True)
|
229
|
+
for ns in self.namespaces
|
230
|
+
]
|
231
|
+
}
|
232
|
+
return self._namespaces_as_dict_cache
|
233
|
+
|
234
|
+
def _matching_namespaces(self, selector: str) -> Any:
|
235
|
+
if selector not in self._matching_namespaces_cache:
|
236
|
+
with self._matching_namespaces_lock:
|
237
|
+
namespaces_as_dict = self._get_namespaces_as_dict()
|
238
|
+
try:
|
239
|
+
self._matching_namespaces_cache[selector] = parse_jsonpath(
|
240
|
+
selector
|
241
|
+
).find(namespaces_as_dict)
|
242
|
+
except JsonPathParserError as e:
|
243
|
+
raise ParameterError(
|
244
|
+
f"Invalid jsonpath expression in namespaceSelector '{selector}' :{e}"
|
245
|
+
)
|
246
|
+
|
247
|
+
return self._matching_namespaces_cache[selector]
|
248
|
+
|
249
|
+
def get_namespaces_by_selector(
|
250
|
+
self, namespace_selector: SaasResourceTemplateTargetNamespaceSelectorV1
|
251
|
+
) -> list[SaasTargetNamespace]:
|
252
|
+
filtered_namespaces: dict[tuple[str, str], Any] = {}
|
253
|
+
|
166
254
|
for include in namespace_selector.json_path_selectors.include:
|
167
|
-
for match in
|
255
|
+
for match in self._matching_namespaces(include):
|
168
256
|
cluster_name = match.value["cluster"]["name"]
|
169
257
|
ns_name = match.value["name"]
|
170
|
-
filtered_namespaces[
|
171
|
-
|
172
|
-
]
|
173
|
-
except JsonPathParserError as e:
|
174
|
-
raise ParameterError(
|
175
|
-
f"Invalid jsonpath expression in namespaceSelector '{include}' :{e}"
|
176
|
-
)
|
258
|
+
filtered_namespaces[(cluster_name, ns_name)] = self.cluster_namespaces[
|
259
|
+
(cluster_name, ns_name)
|
260
|
+
]
|
177
261
|
|
178
|
-
try:
|
179
262
|
for exclude in namespace_selector.json_path_selectors.exclude or []:
|
180
|
-
for match in
|
263
|
+
for match in self._matching_namespaces(exclude):
|
181
264
|
cluster_name = match.value["cluster"]["name"]
|
182
265
|
ns_name = match.value["name"]
|
183
|
-
filtered_namespaces.pop(
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
266
|
+
filtered_namespaces.pop((cluster_name, ns_name), None)
|
267
|
+
|
268
|
+
return list(filtered_namespaces.values())
|
269
|
+
|
270
|
+
def where(
|
271
|
+
self,
|
272
|
+
name: Optional[str] = None,
|
273
|
+
env_name: Optional[str] = None,
|
274
|
+
app_name: Optional[str] = None,
|
275
|
+
) -> list[SaasFile]:
|
276
|
+
if name is None and env_name is None and app_name is None:
|
277
|
+
return self.saas_files
|
278
|
+
|
279
|
+
if name == "" or env_name == "" or app_name == "":
|
280
|
+
return []
|
281
|
+
|
282
|
+
filtered: list[SaasFile] = []
|
283
|
+
for saas_file in self.saas_files[:]:
|
284
|
+
if name and saas_file.name != name:
|
285
|
+
continue
|
286
|
+
|
287
|
+
if app_name and saas_file.app.name != app_name:
|
288
|
+
continue
|
289
|
+
|
290
|
+
sf = saas_file.copy(deep=True)
|
291
|
+
if env_name:
|
292
|
+
for rt in sf.resource_templates[:]:
|
293
|
+
for target in rt.targets[:]:
|
294
|
+
if target.namespace.environment.name != env_name:
|
295
|
+
rt.targets.remove(target)
|
296
|
+
if not rt.targets:
|
297
|
+
sf.resource_templates.remove(rt)
|
298
|
+
if not sf.resource_templates:
|
299
|
+
continue
|
300
|
+
filtered.append(sf)
|
301
|
+
|
302
|
+
return filtered
|
189
303
|
|
190
304
|
|
191
305
|
def convert_parameters_to_json_string(root: dict[str, Any]) -> dict[str, Any]:
|
@@ -207,92 +321,19 @@ def export_model(model: BaseModel) -> dict[str, Any]:
|
|
207
321
|
return convert_parameters_to_json_string(model.dict(by_alias=True))
|
208
322
|
|
209
323
|
|
210
|
-
def create_targets_for_namespace_selector(
|
211
|
-
target: SaasResourceTemplateTargetV2,
|
212
|
-
namespaces: list[SaasTargetNamespace],
|
213
|
-
namespace_selector: SaasResourceTemplateTargetNamespaceSelectorV1,
|
214
|
-
) -> list[SaasResourceTemplateTargetV2]:
|
215
|
-
targets = []
|
216
|
-
for namespace in get_namespaces_by_selector(namespaces, namespace_selector):
|
217
|
-
target_dict = export_model(target)
|
218
|
-
target_dict["namespace"] = export_model(namespace)
|
219
|
-
targets.append(SaasResourceTemplateTargetV2(**target_dict))
|
220
|
-
return targets
|
221
|
-
|
222
|
-
|
223
324
|
def get_saas_files(
|
224
325
|
name: Optional[str] = None,
|
225
326
|
env_name: Optional[str] = None,
|
226
327
|
app_name: Optional[str] = None,
|
227
328
|
query_func: Optional[Callable] = None,
|
228
329
|
namespaces: Optional[list[SaasTargetNamespace]] = None,
|
330
|
+
saas_file_list: Optional[SaasFileList] = None,
|
229
331
|
) -> list[SaasFile]:
|
230
|
-
if not
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
namespaces = namespaces_query(query_func).namespaces or []
|
236
|
-
|
237
|
-
data_saas_files = list(data.saas_files or [])
|
238
|
-
if name:
|
239
|
-
data_saas_files = [sf for sf in data_saas_files if sf.name == name]
|
240
|
-
# resolve namespaceSelectors to real namespaces
|
241
|
-
for saas_file_gql in data_saas_files:
|
242
|
-
for rt_gql in saas_file_gql.resource_templates:
|
243
|
-
for target_gql in rt_gql.targets[:]:
|
244
|
-
# either namespace or namespaceSelector must be set
|
245
|
-
if target_gql.namespace and target_gql.namespace_selector:
|
246
|
-
raise ParameterError(
|
247
|
-
f"SaasFile {saas_file_gql.name}: namespace and namespaceSelector are mutually exclusive"
|
248
|
-
)
|
249
|
-
if not target_gql.provider:
|
250
|
-
target_gql.provider = "static"
|
251
|
-
|
252
|
-
if (
|
253
|
-
target_gql.namespace_selector
|
254
|
-
and not target_gql.provider == "dynamic"
|
255
|
-
):
|
256
|
-
raise ParameterError(
|
257
|
-
f"SaasFile {saas_file_gql.name}: namespaceSelector can only be used with 'provider: dynamic'"
|
258
|
-
)
|
259
|
-
if target_gql.namespace_selector and target_gql.provider == "dynamic":
|
260
|
-
rt_gql.targets.remove(target_gql)
|
261
|
-
rt_gql.targets += create_targets_for_namespace_selector(
|
262
|
-
target_gql, namespaces, target_gql.namespace_selector
|
263
|
-
)
|
264
|
-
# convert SaasFileV2 (with optional resource_templates.targets.namespace field)
|
265
|
-
# to SaasFile (with required resource_templates.targets.namespace field)
|
266
|
-
saas_files.append(SaasFile(**export_model(saas_file_gql)))
|
267
|
-
|
268
|
-
if name is None and env_name is None and app_name is None:
|
269
|
-
return saas_files
|
270
|
-
if name == "" or env_name == "" or app_name == "":
|
271
|
-
return []
|
272
|
-
|
273
|
-
for saas_file in saas_files[:]:
|
274
|
-
if name:
|
275
|
-
if saas_file.name != name:
|
276
|
-
saas_files.remove(saas_file)
|
277
|
-
continue
|
278
|
-
|
279
|
-
if env_name:
|
280
|
-
for rt in saas_file.resource_templates[:]:
|
281
|
-
for target in rt.targets[:]:
|
282
|
-
if target.namespace.environment.name != env_name:
|
283
|
-
rt.targets.remove(target)
|
284
|
-
if not rt.targets:
|
285
|
-
saas_file.resource_templates.remove(rt)
|
286
|
-
if not saas_file.resource_templates:
|
287
|
-
saas_files.remove(saas_file)
|
288
|
-
continue
|
289
|
-
|
290
|
-
if app_name:
|
291
|
-
if saas_file.app.name != app_name:
|
292
|
-
saas_files.remove(saas_file)
|
293
|
-
continue
|
294
|
-
|
295
|
-
return saas_files
|
332
|
+
if not saas_file_list:
|
333
|
+
saas_file_list = SaasFileList(
|
334
|
+
name=name, query_func=query_func, namespaces=namespaces
|
335
|
+
)
|
336
|
+
return saas_file_list.where(env_name=env_name, app_name=app_name)
|
296
337
|
|
297
338
|
|
298
339
|
def get_saasherder_settings(
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc354.dist-info → qontract_reconcile-0.10.1rc355.dist-info}/top_level.txt
RENAMED
File without changes
|