nginx-lens 0.1.0__py3-none-any.whl → 0.1.1__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.
- commands/analyze.py +28 -48
- commands/diff.py +11 -10
- commands/route.py +22 -9
- {nginx_lens-0.1.0.dist-info → nginx_lens-0.1.1.dist-info}/METADATA +1 -1
- {nginx_lens-0.1.0.dist-info → nginx_lens-0.1.1.dist-info}/RECORD +8 -8
- {nginx_lens-0.1.0.dist-info → nginx_lens-0.1.1.dist-info}/WHEEL +0 -0
- {nginx_lens-0.1.0.dist-info → nginx_lens-0.1.1.dist-info}/entry_points.txt +0 -0
- {nginx_lens-0.1.0.dist-info → nginx_lens-0.1.1.dist-info}/top_level.txt +0 -0
commands/analyze.py
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
from rich.console import Console
|
|
3
|
-
from rich.
|
|
4
|
-
from rich.tree import Tree
|
|
3
|
+
from rich.table import Table
|
|
5
4
|
from analyzer.conflicts import find_location_conflicts
|
|
6
5
|
from analyzer.duplicates import find_duplicate_directives
|
|
7
6
|
from analyzer.empty_blocks import find_empty_blocks
|
|
8
|
-
from parser.nginx_parser import parse_nginx_config
|
|
9
7
|
from analyzer.warnings import find_warnings
|
|
10
8
|
from analyzer.unused import find_unused_variables
|
|
9
|
+
from parser.nginx_parser import parse_nginx_config
|
|
11
10
|
|
|
12
11
|
app = typer.Typer()
|
|
13
12
|
console = Console()
|
|
14
13
|
|
|
15
14
|
def analyze(config_path: str = typer.Argument(..., help="Путь к nginx.conf")):
|
|
16
15
|
"""
|
|
17
|
-
Анализирует конфигурацию Nginx на типовые проблемы.
|
|
16
|
+
Анализирует конфигурацию Nginx на типовые проблемы. Выводит таблицу issue_type/issue_description.
|
|
18
17
|
"""
|
|
19
18
|
tree = parse_nginx_config(config_path)
|
|
20
19
|
conflicts = find_location_conflicts(tree)
|
|
@@ -23,48 +22,29 @@ def analyze(config_path: str = typer.Argument(..., help="Путь к nginx.conf"
|
|
|
23
22
|
warnings = find_warnings(tree)
|
|
24
23
|
unused_vars = find_unused_variables(tree)
|
|
25
24
|
|
|
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
|
-
node = root.add("[bold yellow]Потенциальные проблемы[/bold yellow]")
|
|
51
|
-
for w in warnings:
|
|
52
|
-
if w['type'] == 'proxy_pass_no_scheme':
|
|
53
|
-
node.add(f"[yellow]proxy_pass[/yellow] без схемы: [italic]{w['value']}[/italic]")
|
|
54
|
-
elif w['type'] == 'autoindex_on':
|
|
55
|
-
node.add(f"[yellow]autoindex on[/yellow] в блоке [cyan]{w['context'].get('block','')}[/cyan]")
|
|
56
|
-
elif w['type'] == 'if_block':
|
|
57
|
-
node.add(f"[yellow]Директива if[/yellow] внутри блока [cyan]{w['context'].get('block','')}[/cyan]")
|
|
58
|
-
elif w['type'] == 'server_tokens_on':
|
|
59
|
-
node.add(f"[yellow]server_tokens on[/yellow] в блоке [cyan]{w['context'].get('block','')}[/cyan]")
|
|
25
|
+
table = Table(show_header=True, header_style="bold blue")
|
|
26
|
+
table.add_column("issue_type")
|
|
27
|
+
table.add_column("issue_description")
|
|
28
|
+
|
|
29
|
+
for c in conflicts:
|
|
30
|
+
table.add_row("location_conflict", f"server: {c['server'].get('arg', '')} location: {c['location1']} ↔ {c['location2']}")
|
|
31
|
+
for d in dups:
|
|
32
|
+
table.add_row("duplicate_directive", f"{d['directive']} ({d['args']}) — {d['count']} раз в блоке {d['block'].get('block', d['block'])}")
|
|
33
|
+
for e in empties:
|
|
34
|
+
table.add_row("empty_block", f"{e['block']} {e['arg'] or ''}")
|
|
35
|
+
for w in warnings:
|
|
36
|
+
if w['type'] == 'proxy_pass_no_scheme':
|
|
37
|
+
table.add_row("proxy_pass_no_scheme", f"proxy_pass без схемы: {w['value']}")
|
|
38
|
+
elif w['type'] == 'autoindex_on':
|
|
39
|
+
table.add_row("autoindex_on", f"autoindex on в блоке {w['context'].get('block','')}")
|
|
40
|
+
elif w['type'] == 'if_block':
|
|
41
|
+
table.add_row("if_block", f"директива if внутри блока {w['context'].get('block','')}")
|
|
42
|
+
elif w['type'] == 'server_tokens_on':
|
|
43
|
+
table.add_row("server_tokens_on", f"server_tokens on в блоке {w['context'].get('block','')}")
|
|
44
|
+
for v in unused_vars:
|
|
45
|
+
table.add_row("unused_variable", v['name'])
|
|
46
|
+
|
|
47
|
+
if table.row_count == 0:
|
|
48
|
+
console.print("[green]Проблем не найдено[/green]")
|
|
60
49
|
else:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if unused_vars:
|
|
64
|
-
node = root.add("[bold magenta]Неиспользуемые переменные[/bold magenta]")
|
|
65
|
-
for v in unused_vars:
|
|
66
|
-
node.add(f"[magenta]{v['name']}[/magenta]")
|
|
67
|
-
else:
|
|
68
|
-
root.add("[green]Нет неиспользуемых переменных[/green]")
|
|
69
|
-
|
|
70
|
-
console.print(root)
|
|
50
|
+
console.print(table)
|
commands/diff.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
from rich.console import Console
|
|
3
|
-
from rich.
|
|
4
|
-
from rich.text import Text
|
|
3
|
+
from rich.table import Table
|
|
5
4
|
from analyzer.diff import diff_trees
|
|
6
5
|
from parser.nginx_parser import parse_nginx_config
|
|
7
6
|
|
|
@@ -13,7 +12,7 @@ def diff(
|
|
|
13
12
|
config2: str = typer.Argument(..., help="Второй nginx.conf")
|
|
14
13
|
):
|
|
15
14
|
"""
|
|
16
|
-
Сравнивает две конфигурации Nginx и выводит
|
|
15
|
+
Сравнивает две конфигурации Nginx и выводит отличия side-by-side.
|
|
17
16
|
"""
|
|
18
17
|
tree1 = parse_nginx_config(config1)
|
|
19
18
|
tree2 = parse_nginx_config(config2)
|
|
@@ -21,15 +20,17 @@ def diff(
|
|
|
21
20
|
if not diffs:
|
|
22
21
|
console.print("[green]Конфигурации идентичны[/green]")
|
|
23
22
|
return
|
|
24
|
-
|
|
23
|
+
table = Table(show_header=True, header_style="bold blue")
|
|
24
|
+
table.add_column("Config 1", style="red")
|
|
25
|
+
table.add_column("Config 2", style="green")
|
|
25
26
|
for d in diffs:
|
|
26
27
|
path = "/".join(d['path'])
|
|
27
28
|
if d['type'] == 'added':
|
|
28
|
-
|
|
29
|
+
table.add_row("", f"+ {path}")
|
|
29
30
|
elif d['type'] == 'removed':
|
|
30
|
-
|
|
31
|
+
table.add_row(f"- {path}", "")
|
|
31
32
|
elif d['type'] == 'changed':
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
console.print(
|
|
33
|
+
v1 = str(d['value1'])
|
|
34
|
+
v2 = str(d['value2'])
|
|
35
|
+
table.add_row(f"! {path}\n{v1}", f"! {path}\n{v2}")
|
|
36
|
+
console.print(table)
|
commands/route.py
CHANGED
|
@@ -1,30 +1,43 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
from rich.console import Console
|
|
3
|
-
from rich.
|
|
3
|
+
from rich.table import Table
|
|
4
4
|
from analyzer.route import find_route
|
|
5
5
|
from parser.nginx_parser import parse_nginx_config
|
|
6
|
+
from upstream_checker.checker import check_upstreams
|
|
6
7
|
|
|
7
8
|
app = typer.Typer()
|
|
8
9
|
console = Console()
|
|
9
10
|
|
|
10
11
|
def route(
|
|
11
12
|
config_path: str = typer.Argument(..., help="Путь к nginx.conf"),
|
|
12
|
-
url: str = typer.Argument(..., help="URL для маршрутизации (например, http://host/path)")
|
|
13
|
+
url: str = typer.Argument(..., help="URL для маршрутизации (например, http://host/path)"),
|
|
14
|
+
timeout: float = typer.Option(2.0, help="Таймаут проверки (сек)"),
|
|
15
|
+
retries: int = typer.Option(1, help="Количество попыток")
|
|
13
16
|
):
|
|
14
17
|
"""
|
|
15
|
-
Показывает, какой server/location обслуживает указанный URL.
|
|
18
|
+
Показывает, какой server/location обслуживает указанный URL и статус upstream-ов (таблица).
|
|
16
19
|
"""
|
|
17
20
|
tree = parse_nginx_config(config_path)
|
|
18
21
|
res = find_route(tree, url)
|
|
19
22
|
if not res:
|
|
20
|
-
console.print(
|
|
23
|
+
console.print("[red]Не найден подходящий server для {url}[/red]")
|
|
21
24
|
return
|
|
22
25
|
server = res['server']
|
|
23
26
|
location = res['location']
|
|
24
27
|
proxy_pass = res['proxy_pass']
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
table = Table(show_header=True, header_style="bold blue")
|
|
29
|
+
table.add_column("upstream_name")
|
|
30
|
+
table.add_column("upstream_status")
|
|
31
|
+
# Проверяем upstream если есть proxy_pass
|
|
28
32
|
if proxy_pass:
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
upstreams = tree.get_upstreams()
|
|
34
|
+
for name, servers in upstreams.items():
|
|
35
|
+
if name in proxy_pass:
|
|
36
|
+
results = check_upstreams({name: servers}, timeout=timeout, retries=retries)
|
|
37
|
+
for srv in results[name]:
|
|
38
|
+
status = "Healthy" if srv["healthy"] else "Unhealthy"
|
|
39
|
+
color = "green" if srv["healthy"] else "red"
|
|
40
|
+
table.add_row(srv["address"], f"[{color}]{status}[/{color}]")
|
|
41
|
+
else:
|
|
42
|
+
table.add_row("-", "-")
|
|
43
|
+
console.print(table)
|
|
@@ -8,11 +8,11 @@ analyzer/route.py,sha256=2xxQooQEsfn10tzGCZUoP32T0OnTMnPB6qRgBR6not8,2345
|
|
|
8
8
|
analyzer/unused.py,sha256=Ixzv0bPsw9IafblVwLiAOgugdg2dGu1MJDtuoqzPZiY,1066
|
|
9
9
|
analyzer/warnings.py,sha256=eg50TfbE1pJBR6fGUEByqKm5Km1AQBiIy284DOidacI,1244
|
|
10
10
|
commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
commands/analyze.py,sha256=
|
|
11
|
+
commands/analyze.py,sha256=rEOM2h8Ds3S4kcrT5ZPxj6pki912xkihycybJGcERbg,2350
|
|
12
12
|
commands/cli.py,sha256=A47d3vdTDPHRZlRKs02PtxOFdPHjecpXTZyGhQ34r_w,490
|
|
13
|
-
commands/diff.py,sha256=
|
|
13
|
+
commands/diff.py,sha256=BqrBzZJcD7XJWU0HdNos31yANvbwEWR1ZHaVowCoeV0,1282
|
|
14
14
|
commands/health.py,sha256=2QdjIVattoaksW7BrjM2_vqqB18_t7ILeBvKVjaxTdM,1008
|
|
15
|
-
commands/route.py,sha256=
|
|
15
|
+
commands/route.py,sha256=wiNkovPBPnpMau6sWQryOPaP5D8TFOT3s4Ua3XwplLg,1861
|
|
16
16
|
commands/tree.py,sha256=H8kFYueo6mcN82MSgIzAH6Usq9u7sYo2WlY0p8rlN_A,1669
|
|
17
17
|
exporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
18
|
exporter/html.py,sha256=uquEM-WvBt2aV9GshgaI3UVhYd8sD0QQ-OmuNtvYUdU,798
|
|
@@ -21,8 +21,8 @@ parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
21
21
|
parser/nginx_parser.py,sha256=JqZ3clNy4Nf-bmbsx_rJUL7EgRoB79b87eEu_isMeqg,3577
|
|
22
22
|
upstream_checker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
23
|
upstream_checker/checker.py,sha256=9-6CMUTN7gXUACP8EwX722QogfujZyV-WWWUeM3a79k,455
|
|
24
|
-
nginx_lens-0.1.
|
|
25
|
-
nginx_lens-0.1.
|
|
26
|
-
nginx_lens-0.1.
|
|
27
|
-
nginx_lens-0.1.
|
|
28
|
-
nginx_lens-0.1.
|
|
24
|
+
nginx_lens-0.1.1.dist-info/METADATA,sha256=kyCiTNE9IVC5AO9ZVrBQN5xRmCbkOndGz3ofO0R3zlE,476
|
|
25
|
+
nginx_lens-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
26
|
+
nginx_lens-0.1.1.dist-info/entry_points.txt,sha256=qEcecjSyLqcJjbIVlNlTpqAhPqDyaujUV5ZcBTAr3po,48
|
|
27
|
+
nginx_lens-0.1.1.dist-info/top_level.txt,sha256=mxLJO4rZg0rbixVGhplF3fUNFs8vxDIL25ronZNvRy4,51
|
|
28
|
+
nginx_lens-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|