qontract-reconcile 0.10.1rc1149__py3-none-any.whl → 0.10.1rc1151__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.1rc1149.dist-info → qontract_reconcile-0.10.1rc1151.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc1149.dist-info → qontract_reconcile-0.10.1rc1151.dist-info}/RECORD +25 -16
- reconcile/gql_definitions/cost_report/cost_namespaces.py +2 -0
- reconcile/typed_queries/cost_report/cost_namespaces.py +7 -4
- tools/cli_commands/cost_report/aws.py +12 -25
- tools/cli_commands/cost_report/cost_management_api.py +79 -6
- tools/cli_commands/cost_report/model.py +21 -0
- tools/cli_commands/cost_report/openshift.py +7 -20
- tools/cli_commands/cost_report/openshift_cost_optimization.py +187 -0
- tools/cli_commands/cost_report/response.py +56 -1
- tools/cli_commands/cost_report/util.py +13 -0
- tools/cli_commands/cost_report/view.py +128 -2
- tools/cli_commands/test/__init__.py +0 -0
- tools/cli_commands/test/conftest.py +332 -0
- tools/cli_commands/test/test_aws_cost_report.py +258 -0
- tools/cli_commands/test/test_cost_management_api.py +326 -0
- tools/cli_commands/test/test_gpg_encrypt.py +235 -0
- tools/cli_commands/test/test_openshift_cost_optimization_report.py +255 -0
- tools/cli_commands/test/test_openshift_cost_report.py +295 -0
- tools/cli_commands/test/test_util.py +70 -0
- tools/qontract_cli.py +67 -24
- tools/test/test_qontract_cli.py +24 -0
- {qontract_reconcile-0.10.1rc1149.dist-info → qontract_reconcile-0.10.1rc1151.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc1149.dist-info → qontract_reconcile-0.10.1rc1151.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc1149.dist-info → qontract_reconcile-0.10.1rc1151.dist-info}/top_level.txt +0 -0
@@ -2,7 +2,13 @@ from collections import defaultdict
|
|
2
2
|
from collections.abc import Callable, Iterable, Mapping, MutableMapping
|
3
3
|
from typing import Any
|
4
4
|
|
5
|
+
from reconcile.typed_queries.app_interface_vault_settings import (
|
6
|
+
get_app_interface_vault_settings,
|
7
|
+
)
|
5
8
|
from reconcile.typed_queries.cost_report.app_names import App
|
9
|
+
from reconcile.typed_queries.cost_report.settings import get_cost_report_settings
|
10
|
+
from reconcile.utils.gql import GqlApi
|
11
|
+
from reconcile.utils.secret_reader import create_secret_reader
|
6
12
|
from tools.cli_commands.cost_report.model import Report
|
7
13
|
|
8
14
|
|
@@ -57,3 +63,10 @@ def process_reports(
|
|
57
63
|
report_builder=report_builder,
|
58
64
|
)
|
59
65
|
return reports
|
66
|
+
|
67
|
+
|
68
|
+
def fetch_cost_report_secret(gql_api: GqlApi) -> dict[str, str]:
|
69
|
+
vault_settings = get_app_interface_vault_settings(gql_api.query)
|
70
|
+
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
71
|
+
cost_report_settings = get_cost_report_settings(gql_api)
|
72
|
+
return secret_reader.read_all_secret(cost_report_settings.credentials)
|
@@ -1,10 +1,10 @@
|
|
1
|
-
from collections.abc import Callable, Mapping
|
1
|
+
from collections.abc import Callable, Iterable, Mapping
|
2
2
|
from decimal import Decimal
|
3
3
|
from typing import Any
|
4
4
|
|
5
5
|
from pydantic import BaseModel
|
6
6
|
|
7
|
-
from tools.cli_commands.cost_report.model import Report
|
7
|
+
from tools.cli_commands.cost_report.model import OptimizationReport, Report
|
8
8
|
|
9
9
|
LAYOUT = """\
|
10
10
|
[TOC]
|
@@ -15,6 +15,13 @@ LAYOUT = """\
|
|
15
15
|
{cost_breakdown}\
|
16
16
|
"""
|
17
17
|
|
18
|
+
OPTIMIZATION_LAYOUT = """\
|
19
|
+
[TOC]
|
20
|
+
|
21
|
+
{header}
|
22
|
+
{optimizations}\
|
23
|
+
"""
|
24
|
+
|
18
25
|
AWS_HEADER = """\
|
19
26
|
# AWS Cost Report
|
20
27
|
"""
|
@@ -23,6 +30,19 @@ OPENSHIFT_HEADER = """\
|
|
23
30
|
# OpenShift Cost Report
|
24
31
|
"""
|
25
32
|
|
33
|
+
OPTIMIZATION_HEADER = """\
|
34
|
+
# OpenShift Cost Optimization Report
|
35
|
+
|
36
|
+
Report is generated for optimization enabled namespaces
|
37
|
+
(`insights_cost_management_optimizations='true'` in namespace `labels`).
|
38
|
+
|
39
|
+
In Cost optimizations, recommendations get generated when
|
40
|
+
CPU usage is at or above the 60th percentile and
|
41
|
+
memory usage is at the 100th percentile.
|
42
|
+
|
43
|
+
View details in [Cost Management Optimizations](https://console.redhat.com/openshift/cost-management/optimizations).
|
44
|
+
"""
|
45
|
+
|
26
46
|
AWS_SUMMARY = """\
|
27
47
|
## Summary
|
28
48
|
|
@@ -107,6 +127,14 @@ TOTAL_COST = """\
|
|
107
127
|
Total Cost: {total}
|
108
128
|
"""
|
109
129
|
|
130
|
+
OPTIMIZATION = """\
|
131
|
+
## {app_name}
|
132
|
+
|
133
|
+
```json:table
|
134
|
+
{json_table}
|
135
|
+
```
|
136
|
+
"""
|
137
|
+
|
110
138
|
|
111
139
|
class TableField(BaseModel):
|
112
140
|
key: str
|
@@ -146,6 +174,19 @@ class ViewChildAppReport(BaseModel):
|
|
146
174
|
total: Decimal
|
147
175
|
|
148
176
|
|
177
|
+
class ViewOptimizationReportItem(BaseModel):
|
178
|
+
namespace: str
|
179
|
+
workload: str
|
180
|
+
current_cpu_limit: str | None
|
181
|
+
current_cpu_request: str | None
|
182
|
+
current_memory_limit: str | None
|
183
|
+
current_memory_request: str | None
|
184
|
+
recommend_cpu_limit: str | None
|
185
|
+
recommend_cpu_request: str | None
|
186
|
+
recommend_memory_limit: str | None
|
187
|
+
recommend_memory_request: str | None
|
188
|
+
|
189
|
+
|
149
190
|
def format_cost_value(value: Decimal) -> str:
|
150
191
|
return f"${value:,.2f}"
|
151
192
|
|
@@ -396,3 +437,88 @@ def render_openshift_cost_report(
|
|
396
437
|
item_cost_renderer=render_openshift_workloads_cost,
|
397
438
|
),
|
398
439
|
)
|
440
|
+
|
441
|
+
|
442
|
+
def render_optimization(
|
443
|
+
report: OptimizationReport,
|
444
|
+
) -> str:
|
445
|
+
items = [
|
446
|
+
ViewOptimizationReportItem(
|
447
|
+
namespace=f"{i.cluster}/{i.project}",
|
448
|
+
workload=f"{i.workload_type}/{i.workload}/{i.container}",
|
449
|
+
current_cpu_limit=i.current_cpu_limit,
|
450
|
+
current_cpu_request=i.current_cpu_request,
|
451
|
+
current_memory_limit=i.current_memory_limit,
|
452
|
+
current_memory_request=i.current_memory_request,
|
453
|
+
recommend_cpu_limit=i.recommend_cpu_limit,
|
454
|
+
recommend_cpu_request=i.recommend_cpu_request,
|
455
|
+
recommend_memory_limit=i.recommend_memory_limit,
|
456
|
+
recommend_memory_request=i.recommend_memory_request,
|
457
|
+
)
|
458
|
+
for i in report.items
|
459
|
+
]
|
460
|
+
json_table = JsonTable(
|
461
|
+
filter=True,
|
462
|
+
items=sorted(items, key=lambda item: (item.namespace, item.workload)),
|
463
|
+
fields=[
|
464
|
+
TableField(key="namespace", label="Namespace", sortable=True),
|
465
|
+
TableField(key="workload", label="Workload", sortable=True),
|
466
|
+
TableField(
|
467
|
+
key="current_cpu_request", label="Current CPU Request", sortable=True
|
468
|
+
),
|
469
|
+
TableField(
|
470
|
+
key="recommend_cpu_request",
|
471
|
+
label="Recommend CPU Request",
|
472
|
+
sortable=True,
|
473
|
+
),
|
474
|
+
TableField(
|
475
|
+
key="current_cpu_limit", label="Current CPU Limit", sortable=True
|
476
|
+
),
|
477
|
+
TableField(
|
478
|
+
key="recommend_cpu_limit", label="Recommend CPU Limit", sortable=True
|
479
|
+
),
|
480
|
+
TableField(
|
481
|
+
key="current_memory_request",
|
482
|
+
label="Current Memory Request",
|
483
|
+
sortable=True,
|
484
|
+
),
|
485
|
+
TableField(
|
486
|
+
key="recommend_memory_request",
|
487
|
+
label="Recommend Memory Request",
|
488
|
+
sortable=True,
|
489
|
+
),
|
490
|
+
TableField(
|
491
|
+
key="current_memory_limit", label="Current Memory Limit", sortable=True
|
492
|
+
),
|
493
|
+
TableField(
|
494
|
+
key="recommend_memory_limit",
|
495
|
+
label="Recommend Memory Limit",
|
496
|
+
sortable=True,
|
497
|
+
),
|
498
|
+
],
|
499
|
+
)
|
500
|
+
return OPTIMIZATION.format(
|
501
|
+
app_name=report.app_name,
|
502
|
+
json_table=json_table.json(indent=2),
|
503
|
+
)
|
504
|
+
|
505
|
+
|
506
|
+
def render_optimizations(
|
507
|
+
reports: Iterable[OptimizationReport],
|
508
|
+
) -> str:
|
509
|
+
return "\n".join(
|
510
|
+
render_optimization(report=report)
|
511
|
+
for report in sorted(
|
512
|
+
reports,
|
513
|
+
key=lambda item: item.app_name.lower(),
|
514
|
+
)
|
515
|
+
)
|
516
|
+
|
517
|
+
|
518
|
+
def render_openshift_cost_optimization_report(
|
519
|
+
reports: Iterable[OptimizationReport],
|
520
|
+
) -> str:
|
521
|
+
return OPTIMIZATION_LAYOUT.format(
|
522
|
+
header=OPTIMIZATION_HEADER,
|
523
|
+
optimizations=render_optimizations(reports),
|
524
|
+
)
|
File without changes
|
@@ -0,0 +1,332 @@
|
|
1
|
+
from collections.abc import Callable
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
|
6
|
+
from tools.cli_commands.cost_report.response import (
|
7
|
+
OpenShiftCostOptimizationReportResponse,
|
8
|
+
OpenShiftCostOptimizationResponse,
|
9
|
+
RecommendationEngineResponse,
|
10
|
+
RecommendationEnginesResponse,
|
11
|
+
RecommendationResourcesResponse,
|
12
|
+
RecommendationsResponse,
|
13
|
+
RecommendationTermResponse,
|
14
|
+
RecommendationTermsResponse,
|
15
|
+
ResourceConfigResponse,
|
16
|
+
ResourceResponse,
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
@pytest.fixture
|
21
|
+
def fx() -> Callable:
|
22
|
+
def _fx(name: str) -> str:
|
23
|
+
return (Path(__file__).parent / "fixtures" / name).read_text()
|
24
|
+
|
25
|
+
return _fx
|
26
|
+
|
27
|
+
|
28
|
+
COST_MANAGEMENT_CONSOLE_BASE_URL = (
|
29
|
+
"https://console.redhat.com/openshift/cost-management"
|
30
|
+
)
|
31
|
+
|
32
|
+
COST_MANAGEMENT_API_HOST = "https://host/"
|
33
|
+
|
34
|
+
COST_REPORT_SECRET = {
|
35
|
+
"api_base_url": f"{COST_MANAGEMENT_API_HOST}/v1",
|
36
|
+
"token_url": "token_url",
|
37
|
+
"client_id": "client_id",
|
38
|
+
"client_secret": "client_secret",
|
39
|
+
"scope": "scope",
|
40
|
+
"console_base_url": COST_MANAGEMENT_CONSOLE_BASE_URL,
|
41
|
+
}
|
42
|
+
|
43
|
+
OPENSHIFT_COST_OPTIMIZATION_RESPONSE = OpenShiftCostOptimizationReportResponse(
|
44
|
+
data=[
|
45
|
+
OpenShiftCostOptimizationResponse(
|
46
|
+
cluster_alias="some-cluster",
|
47
|
+
cluster_uuid="some-cluster-uuid",
|
48
|
+
container="test",
|
49
|
+
id="id-uuid",
|
50
|
+
project="some-project",
|
51
|
+
workload="test-deployment",
|
52
|
+
workload_type="deployment",
|
53
|
+
recommendations=RecommendationsResponse(
|
54
|
+
current=RecommendationResourcesResponse(
|
55
|
+
limits=ResourceResponse(
|
56
|
+
cpu=ResourceConfigResponse(amount=4),
|
57
|
+
memory=ResourceConfigResponse(amount=5, format="Gi"),
|
58
|
+
),
|
59
|
+
requests=ResourceResponse(
|
60
|
+
cpu=ResourceConfigResponse(amount=1),
|
61
|
+
memory=ResourceConfigResponse(amount=400, format="Mi"),
|
62
|
+
),
|
63
|
+
),
|
64
|
+
recommendation_terms=RecommendationTermsResponse(
|
65
|
+
long_term=RecommendationTermResponse(),
|
66
|
+
medium_term=RecommendationTermResponse(),
|
67
|
+
short_term=RecommendationTermResponse(
|
68
|
+
recommendation_engines=RecommendationEnginesResponse(
|
69
|
+
cost=RecommendationEngineResponse(
|
70
|
+
config=RecommendationResourcesResponse(
|
71
|
+
limits=ResourceResponse(
|
72
|
+
cpu=ResourceConfigResponse(amount=5),
|
73
|
+
memory=ResourceConfigResponse(
|
74
|
+
amount=6, format="Gi"
|
75
|
+
),
|
76
|
+
),
|
77
|
+
requests=ResourceResponse(
|
78
|
+
cpu=ResourceConfigResponse(amount=3),
|
79
|
+
memory=ResourceConfigResponse(
|
80
|
+
amount=700, format="Mi"
|
81
|
+
),
|
82
|
+
),
|
83
|
+
),
|
84
|
+
variation=RecommendationResourcesResponse(
|
85
|
+
limits=ResourceResponse(
|
86
|
+
cpu=ResourceConfigResponse(amount=1),
|
87
|
+
memory=ResourceConfigResponse(
|
88
|
+
amount=1, format="Gi"
|
89
|
+
),
|
90
|
+
),
|
91
|
+
requests=ResourceResponse(
|
92
|
+
cpu=ResourceConfigResponse(amount=2),
|
93
|
+
memory=ResourceConfigResponse(
|
94
|
+
amount=300, format="Mi"
|
95
|
+
),
|
96
|
+
),
|
97
|
+
),
|
98
|
+
),
|
99
|
+
performance=RecommendationEngineResponse(
|
100
|
+
config=RecommendationResourcesResponse(
|
101
|
+
limits=ResourceResponse(
|
102
|
+
cpu=ResourceConfigResponse(amount=3),
|
103
|
+
memory=ResourceConfigResponse(
|
104
|
+
amount=6, format="Gi"
|
105
|
+
),
|
106
|
+
),
|
107
|
+
requests=ResourceResponse(
|
108
|
+
cpu=ResourceConfigResponse(
|
109
|
+
amount=600, format="millicores"
|
110
|
+
),
|
111
|
+
memory=ResourceConfigResponse(
|
112
|
+
amount=700, format="Mi"
|
113
|
+
),
|
114
|
+
),
|
115
|
+
),
|
116
|
+
variation=RecommendationResourcesResponse(
|
117
|
+
limits=ResourceResponse(
|
118
|
+
cpu=ResourceConfigResponse(amount=-1),
|
119
|
+
memory=ResourceConfigResponse(
|
120
|
+
amount=1, format="Gi"
|
121
|
+
),
|
122
|
+
),
|
123
|
+
requests=ResourceResponse(
|
124
|
+
cpu=ResourceConfigResponse(
|
125
|
+
amount=-400, format="millicores"
|
126
|
+
),
|
127
|
+
memory=ResourceConfigResponse(
|
128
|
+
amount=300, format="Mi"
|
129
|
+
),
|
130
|
+
),
|
131
|
+
),
|
132
|
+
),
|
133
|
+
)
|
134
|
+
),
|
135
|
+
),
|
136
|
+
),
|
137
|
+
)
|
138
|
+
]
|
139
|
+
)
|
140
|
+
|
141
|
+
OPENSHIFT_COST_OPTIMIZATION_WITH_FUZZY_MATCH_RESPONSE = (
|
142
|
+
OpenShiftCostOptimizationReportResponse(
|
143
|
+
data=[
|
144
|
+
OpenShiftCostOptimizationResponse(
|
145
|
+
cluster_alias="some-cluster",
|
146
|
+
cluster_uuid="some-cluster-uuid",
|
147
|
+
container="test",
|
148
|
+
id="id-uuid",
|
149
|
+
project="some-project",
|
150
|
+
workload="test-deployment",
|
151
|
+
workload_type="deployment",
|
152
|
+
recommendations=RecommendationsResponse(
|
153
|
+
current=RecommendationResourcesResponse(
|
154
|
+
limits=ResourceResponse(
|
155
|
+
cpu=ResourceConfigResponse(amount=4),
|
156
|
+
memory=ResourceConfigResponse(amount=5, format="Gi"),
|
157
|
+
),
|
158
|
+
requests=ResourceResponse(
|
159
|
+
cpu=ResourceConfigResponse(amount=1),
|
160
|
+
memory=ResourceConfigResponse(amount=400, format="Mi"),
|
161
|
+
),
|
162
|
+
),
|
163
|
+
recommendation_terms=RecommendationTermsResponse(
|
164
|
+
long_term=RecommendationTermResponse(),
|
165
|
+
medium_term=RecommendationTermResponse(),
|
166
|
+
short_term=RecommendationTermResponse(
|
167
|
+
recommendation_engines=RecommendationEnginesResponse(
|
168
|
+
cost=RecommendationEngineResponse(
|
169
|
+
config=RecommendationResourcesResponse(
|
170
|
+
limits=ResourceResponse(
|
171
|
+
cpu=ResourceConfigResponse(amount=5),
|
172
|
+
memory=ResourceConfigResponse(
|
173
|
+
amount=6, format="Gi"
|
174
|
+
),
|
175
|
+
),
|
176
|
+
requests=ResourceResponse(
|
177
|
+
cpu=ResourceConfigResponse(amount=3),
|
178
|
+
memory=ResourceConfigResponse(
|
179
|
+
amount=700, format="Mi"
|
180
|
+
),
|
181
|
+
),
|
182
|
+
),
|
183
|
+
variation=RecommendationResourcesResponse(
|
184
|
+
limits=ResourceResponse(
|
185
|
+
cpu=ResourceConfigResponse(amount=1),
|
186
|
+
memory=ResourceConfigResponse(
|
187
|
+
amount=1, format="Gi"
|
188
|
+
),
|
189
|
+
),
|
190
|
+
requests=ResourceResponse(
|
191
|
+
cpu=ResourceConfigResponse(amount=2),
|
192
|
+
memory=ResourceConfigResponse(
|
193
|
+
amount=300, format="Mi"
|
194
|
+
),
|
195
|
+
),
|
196
|
+
),
|
197
|
+
),
|
198
|
+
performance=RecommendationEngineResponse(
|
199
|
+
config=RecommendationResourcesResponse(
|
200
|
+
limits=ResourceResponse(
|
201
|
+
cpu=ResourceConfigResponse(amount=3),
|
202
|
+
memory=ResourceConfigResponse(
|
203
|
+
amount=6, format="Gi"
|
204
|
+
),
|
205
|
+
),
|
206
|
+
requests=ResourceResponse(
|
207
|
+
cpu=ResourceConfigResponse(
|
208
|
+
amount=600, format="millicores"
|
209
|
+
),
|
210
|
+
memory=ResourceConfigResponse(
|
211
|
+
amount=700, format="Mi"
|
212
|
+
),
|
213
|
+
),
|
214
|
+
),
|
215
|
+
variation=RecommendationResourcesResponse(
|
216
|
+
limits=ResourceResponse(
|
217
|
+
cpu=ResourceConfigResponse(amount=-1),
|
218
|
+
memory=ResourceConfigResponse(
|
219
|
+
amount=1, format="Gi"
|
220
|
+
),
|
221
|
+
),
|
222
|
+
requests=ResourceResponse(
|
223
|
+
cpu=ResourceConfigResponse(
|
224
|
+
amount=-400, format="millicores"
|
225
|
+
),
|
226
|
+
memory=ResourceConfigResponse(
|
227
|
+
amount=300, format="Mi"
|
228
|
+
),
|
229
|
+
),
|
230
|
+
),
|
231
|
+
),
|
232
|
+
)
|
233
|
+
),
|
234
|
+
),
|
235
|
+
),
|
236
|
+
),
|
237
|
+
OpenShiftCostOptimizationResponse(
|
238
|
+
cluster_alias="some-cluster2",
|
239
|
+
cluster_uuid="some-cluster-uuid2",
|
240
|
+
container="test",
|
241
|
+
id="id-uuid",
|
242
|
+
project="some-project2",
|
243
|
+
workload="test-deployment",
|
244
|
+
workload_type="deployment",
|
245
|
+
recommendations=RecommendationsResponse(
|
246
|
+
current=RecommendationResourcesResponse(
|
247
|
+
limits=ResourceResponse(
|
248
|
+
cpu=ResourceConfigResponse(amount=4),
|
249
|
+
memory=ResourceConfigResponse(amount=5, format="Gi"),
|
250
|
+
),
|
251
|
+
requests=ResourceResponse(
|
252
|
+
cpu=ResourceConfigResponse(amount=1),
|
253
|
+
memory=ResourceConfigResponse(amount=400, format="Mi"),
|
254
|
+
),
|
255
|
+
),
|
256
|
+
recommendation_terms=RecommendationTermsResponse(
|
257
|
+
long_term=RecommendationTermResponse(),
|
258
|
+
medium_term=RecommendationTermResponse(),
|
259
|
+
short_term=RecommendationTermResponse(
|
260
|
+
recommendation_engines=RecommendationEnginesResponse(
|
261
|
+
cost=RecommendationEngineResponse(
|
262
|
+
config=RecommendationResourcesResponse(
|
263
|
+
limits=ResourceResponse(
|
264
|
+
cpu=ResourceConfigResponse(amount=5),
|
265
|
+
memory=ResourceConfigResponse(
|
266
|
+
amount=6, format="Gi"
|
267
|
+
),
|
268
|
+
),
|
269
|
+
requests=ResourceResponse(
|
270
|
+
cpu=ResourceConfigResponse(amount=3),
|
271
|
+
memory=ResourceConfigResponse(
|
272
|
+
amount=700, format="Mi"
|
273
|
+
),
|
274
|
+
),
|
275
|
+
),
|
276
|
+
variation=RecommendationResourcesResponse(
|
277
|
+
limits=ResourceResponse(
|
278
|
+
cpu=ResourceConfigResponse(amount=1),
|
279
|
+
memory=ResourceConfigResponse(
|
280
|
+
amount=1, format="Gi"
|
281
|
+
),
|
282
|
+
),
|
283
|
+
requests=ResourceResponse(
|
284
|
+
cpu=ResourceConfigResponse(amount=2),
|
285
|
+
memory=ResourceConfigResponse(
|
286
|
+
amount=300, format="Mi"
|
287
|
+
),
|
288
|
+
),
|
289
|
+
),
|
290
|
+
),
|
291
|
+
performance=RecommendationEngineResponse(
|
292
|
+
config=RecommendationResourcesResponse(
|
293
|
+
limits=ResourceResponse(
|
294
|
+
cpu=ResourceConfigResponse(amount=3),
|
295
|
+
memory=ResourceConfigResponse(
|
296
|
+
amount=6, format="Gi"
|
297
|
+
),
|
298
|
+
),
|
299
|
+
requests=ResourceResponse(
|
300
|
+
cpu=ResourceConfigResponse(
|
301
|
+
amount=600, format="millicores"
|
302
|
+
),
|
303
|
+
memory=ResourceConfigResponse(
|
304
|
+
amount=700, format="Mi"
|
305
|
+
),
|
306
|
+
),
|
307
|
+
),
|
308
|
+
variation=RecommendationResourcesResponse(
|
309
|
+
limits=ResourceResponse(
|
310
|
+
cpu=ResourceConfigResponse(amount=-1),
|
311
|
+
memory=ResourceConfigResponse(
|
312
|
+
amount=1, format="Gi"
|
313
|
+
),
|
314
|
+
),
|
315
|
+
requests=ResourceResponse(
|
316
|
+
cpu=ResourceConfigResponse(
|
317
|
+
amount=-400, format="millicores"
|
318
|
+
),
|
319
|
+
memory=ResourceConfigResponse(
|
320
|
+
amount=300, format="Mi"
|
321
|
+
),
|
322
|
+
),
|
323
|
+
),
|
324
|
+
),
|
325
|
+
)
|
326
|
+
),
|
327
|
+
),
|
328
|
+
),
|
329
|
+
),
|
330
|
+
]
|
331
|
+
)
|
332
|
+
)
|