1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
import itertools
from typing import Any
from rich.table import Table
from robusta_krr.core.abstract import formatters
from robusta_krr.core.models.allocations import RecommendationValue
from robusta_krr.core.models.result import ResourceScan, ResourceType, Result
from robusta_krr.core.models.config import settings
from robusta_krr.utils import resource_units
NONE_LITERAL = "unset"
NAN_LITERAL = "?"
def _format(value: RecommendationValue) -> str:
if value is None:
return NONE_LITERAL
elif isinstance(value, str):
return NAN_LITERAL
else:
return resource_units.format(value)
def __calc_diff(allocated, recommended, selector, multiplier=1) -> str:
if recommended is None or isinstance(recommended.value, str) or selector != "requests":
return ""
else:
reccomended_val = recommended.value if isinstance(recommended.value, (int, float)) else 0
allocated_val = allocated if isinstance(allocated, (int, float)) else 0
diff_val = reccomended_val - allocated_val
diff_sign = "[green]+[/green]" if diff_val >= 0 else "[red]-[/red]"
return f"{diff_sign}{_format(abs(diff_val) * multiplier)}"
def _format_request_str(item: ResourceScan, resource: ResourceType, selector: str) -> str:
allocated = getattr(item.object.allocations, selector)[resource]
info = item.recommended.info.get(resource)
recommended = getattr(item.recommended, selector)[resource]
severity = recommended.severity
if allocated is None and recommended.value is None:
return f"[{severity.color}]{NONE_LITERAL}[/{severity.color}]"
diff = __calc_diff(allocated, recommended, selector)
if diff != "":
diff = f"({diff}) "
return (
diff
+ f"[{severity.color}]"
+ _format(allocated)
+ " -> "
+ _format(recommended.value)
+ f"[/{severity.color}]"
+ (f" [grey27]({info})[/grey27]" if info else "")
)
def _format_total_diff(item: ResourceScan, resource: ResourceType, pods_current: int) -> str:
selector = "requests"
allocated = getattr(item.object.allocations, selector)[resource]
recommended = getattr(item.recommended, selector)[resource]
return __calc_diff(allocated, recommended, selector, pods_current)
@formatters.register(rich_console=True)
def table(result: Result) -> Table:
"""Format the result as text.
:param result: The result to format.
:type result: :class:`core.result.Result`
:returns: The formatted results.
:rtype: str
"""
table = Table(
show_header=True,
header_style="bold magenta",
title=f"\n{result.description}\n" if result.description else None,
title_justify="left",
title_style="",
caption=f"{result.score} points - {result.score_letter}",
)
cluster_count = len(set(item.object.cluster for item in result.scans))
table.add_column("Number", justify="right", no_wrap=True)
if cluster_count > 1 or settings.show_cluster_name:
table.add_column("Cluster", style="cyan")
table.add_column("Namespace", style="cyan")
table.add_column("Name", style="cyan")
table.add_column("Pods", style="cyan")
table.add_column("Old Pods", style="cyan")
table.add_column("Type", style="cyan")
table.add_column("Container", style="cyan")
for resource in ResourceType:
table.add_column(f"{resource.name} Diff")
table.add_column(f"{resource.name} Requests")
table.add_column(f"{resource.name} Limits")
for _, group in itertools.groupby(
enumerate(result.scans), key=lambda x: (x[1].object.cluster, x[1].object.namespace, x[1].object.name)
):
group_items = list(group)
for j, (i, item) in enumerate(group_items):
last_row = j == len(group_items) - 1
full_info_row = j == 0
cells: list[Any] = [f"[{item.severity.color}]{i + 1}.[/{item.severity.color}]"]
if cluster_count > 1:
cells.append(item.object.cluster if full_info_row else "")
cells += [
item.object.namespace if full_info_row else "",
item.object.name if full_info_row else "",
f"{item.object.current_pods_count}" if full_info_row else "",
f"{item.object.deleted_pods_count}" if full_info_row else "",
item.object.kind if full_info_row else "",
item.object.container,
]
for resource in ResourceType:
cells.append(_format_total_diff(item, resource, item.object.current_pods_count))
cells += [_format_request_str(item, resource, selector) for selector in ["requests", "limits"]]
table.add_row(*cells, end_section=last_row)
return table
|