nginx-lens 0.1.5__py3-none-any.whl → 0.1.6__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 +8 -1
- commands/diff.py +30 -18
- commands/graph.py +52 -8
- commands/include.py +8 -1
- commands/route.py +5 -1
- commands/syntax.py +5 -2
- commands/tree.py +8 -1
- {nginx_lens-0.1.5.dist-info → nginx_lens-0.1.6.dist-info}/METADATA +1 -1
- {nginx_lens-0.1.5.dist-info → nginx_lens-0.1.6.dist-info}/RECORD +12 -12
- {nginx_lens-0.1.5.dist-info → nginx_lens-0.1.6.dist-info}/WHEEL +0 -0
- {nginx_lens-0.1.5.dist-info → nginx_lens-0.1.6.dist-info}/entry_points.txt +0 -0
- {nginx_lens-0.1.5.dist-info → nginx_lens-0.1.6.dist-info}/top_level.txt +0 -0
commands/analyze.py
CHANGED
|
@@ -58,7 +58,14 @@ def analyze(config_path: str = typer.Argument(..., help="Путь к nginx.conf"
|
|
|
58
58
|
Пример:
|
|
59
59
|
nginx-lens analyze /etc/nginx/nginx.conf
|
|
60
60
|
"""
|
|
61
|
-
|
|
61
|
+
try:
|
|
62
|
+
tree = parse_nginx_config(config_path)
|
|
63
|
+
except FileNotFoundError:
|
|
64
|
+
console.print(f"[red]Файл {config_path} не найден. Проверьте путь к конфигу.[/red]")
|
|
65
|
+
return
|
|
66
|
+
except Exception as e:
|
|
67
|
+
console.print(f"[red]Ошибка при разборе {config_path}: {e}[/red]")
|
|
68
|
+
return
|
|
62
69
|
conflicts = find_location_conflicts(tree)
|
|
63
70
|
dups = find_duplicate_directives(tree)
|
|
64
71
|
empties = find_empty_blocks(tree)
|
commands/diff.py
CHANGED
|
@@ -3,6 +3,7 @@ from rich.console import Console
|
|
|
3
3
|
from rich.table import Table
|
|
4
4
|
from analyzer.diff import diff_trees
|
|
5
5
|
from parser.nginx_parser import parse_nginx_config
|
|
6
|
+
import difflib
|
|
6
7
|
|
|
7
8
|
app = typer.Typer()
|
|
8
9
|
console = Console()
|
|
@@ -12,28 +13,39 @@ def diff(
|
|
|
12
13
|
config2: str = typer.Argument(..., help="Второй nginx.conf")
|
|
13
14
|
):
|
|
14
15
|
"""
|
|
15
|
-
Сравнивает две конфигурации Nginx и выводит отличия side-by-side
|
|
16
|
+
Сравнивает две конфигурации Nginx и выводит отличия построчно side-by-side с подсветкой.
|
|
16
17
|
|
|
17
18
|
Пример:
|
|
18
19
|
nginx-lens diff /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
|
|
19
20
|
"""
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
try:
|
|
22
|
+
with open(config1) as f1, open(config2) as f2:
|
|
23
|
+
lines1 = f1.readlines()
|
|
24
|
+
lines2 = f2.readlines()
|
|
25
|
+
except FileNotFoundError as e:
|
|
26
|
+
console.print(f"[red]Файл {e.filename} не найден. Проверьте путь к конфигу.[/red]")
|
|
25
27
|
return
|
|
28
|
+
except Exception as e:
|
|
29
|
+
console.print(f"[red]Ошибка при чтении файлов: {e}[/red]")
|
|
30
|
+
return
|
|
31
|
+
maxlen = max(len(lines1), len(lines2))
|
|
32
|
+
# Выравниваем длины
|
|
33
|
+
lines1 += [''] * (maxlen - len(lines1))
|
|
34
|
+
lines2 += [''] * (maxlen - len(lines2))
|
|
26
35
|
table = Table(show_header=True, header_style="bold blue")
|
|
27
|
-
table.add_column("
|
|
28
|
-
table.add_column("Config
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
table.add_column("№", style="dim", width=4)
|
|
37
|
+
table.add_column("Config 1", style="white")
|
|
38
|
+
table.add_column("№", style="dim", width=4)
|
|
39
|
+
table.add_column("Config 2", style="white")
|
|
40
|
+
for i in range(maxlen):
|
|
41
|
+
l1 = lines1[i].rstrip('\n')
|
|
42
|
+
l2 = lines2[i].rstrip('\n')
|
|
43
|
+
n1 = str(i+1) if l1 else ''
|
|
44
|
+
n2 = str(i+1) if l2 else ''
|
|
45
|
+
if l1 == l2:
|
|
46
|
+
table.add_row(n1, l1, n2, l2)
|
|
47
|
+
else:
|
|
48
|
+
style1 = "red" if l1 else "on red"
|
|
49
|
+
style2 = "green" if l2 else "on green"
|
|
50
|
+
table.add_row(f"[bold]{n1}[/bold]" if l1 else n1, f"[{style1}]{l1}[/{style1}]" if l1 or l2 else '', f"[bold]{n2}[/bold]" if l2 else n2, f"[{style2}]{l2}[/{style2}]" if l1 or l2 else '')
|
|
39
51
|
console.print(table)
|
commands/graph.py
CHANGED
|
@@ -59,17 +59,61 @@ def graph(
|
|
|
59
59
|
console.print("[yellow]Не найдено ни одного маршрута[/yellow]")
|
|
60
60
|
return
|
|
61
61
|
# Красивый вывод
|
|
62
|
+
seen = set()
|
|
62
63
|
for route in routes:
|
|
64
|
+
if not route or route[0][0] != 'server':
|
|
65
|
+
continue
|
|
66
|
+
key = tuple(route)
|
|
67
|
+
if key in seen:
|
|
68
|
+
continue
|
|
69
|
+
seen.add(key)
|
|
63
70
|
t = Text()
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
# Получаем label для server
|
|
72
|
+
server_val = route[0][1]
|
|
73
|
+
server_block = None
|
|
74
|
+
# Найти сам блок server по arg
|
|
75
|
+
for d in tree.directives:
|
|
76
|
+
if d.get('block') == 'server' and (d.get('arg','') == server_val or (not d.get('arg') and (server_val == '[no arg]' or not server_val))):
|
|
77
|
+
server_block = d
|
|
78
|
+
break
|
|
79
|
+
label = get_server_label(server_block) if server_block else (server_val or 'default')
|
|
80
|
+
t.append(f"[", style="white")
|
|
81
|
+
t.append(f"server: {label}", style="bold blue")
|
|
82
|
+
t.append("]", style="white")
|
|
83
|
+
for i, (typ, val) in enumerate(route[1:]):
|
|
84
|
+
if typ == 'location':
|
|
85
|
+
t.append(f" -> [", style="white")
|
|
86
|
+
t.append(f"location: {val}", style="yellow")
|
|
87
|
+
t.append("]", style="white")
|
|
69
88
|
elif typ == 'proxy_pass':
|
|
70
89
|
t.append(f" -> proxy_pass: {val}", style="green")
|
|
71
90
|
elif typ == 'upstream':
|
|
72
|
-
t.append(f" ->
|
|
91
|
+
t.append(f" -> [", style="white")
|
|
92
|
+
t.append(f"upstream: {val}", style="magenta")
|
|
93
|
+
t.append("]", style="white")
|
|
73
94
|
elif typ == 'upstream_server':
|
|
74
|
-
t.append(f" ->
|
|
75
|
-
|
|
95
|
+
t.append(f" -> [", style="white")
|
|
96
|
+
t.append(f"server: {val}", style="grey50")
|
|
97
|
+
t.append("]", style="white")
|
|
98
|
+
console.print(t)
|
|
99
|
+
|
|
100
|
+
def get_server_label(server_block):
|
|
101
|
+
arg = server_block.get('arg')
|
|
102
|
+
if arg and arg != '[no arg]':
|
|
103
|
+
return arg
|
|
104
|
+
# Ищем server_name
|
|
105
|
+
names = []
|
|
106
|
+
listens = []
|
|
107
|
+
for sub in server_block.get('directives', []):
|
|
108
|
+
if sub.get('directive') == 'server_name':
|
|
109
|
+
names += sub.get('args', '').split()
|
|
110
|
+
if sub.get('directive') == 'listen':
|
|
111
|
+
listens.append(sub.get('args', ''))
|
|
112
|
+
if names:
|
|
113
|
+
return ' '.join(names)
|
|
114
|
+
if listens:
|
|
115
|
+
return ','.join(listens)
|
|
116
|
+
return 'default'
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
app()
|
commands/include.py
CHANGED
|
@@ -18,7 +18,14 @@ def include_tree(
|
|
|
18
18
|
nginx-lens include-tree /etc/nginx/nginx.conf
|
|
19
19
|
nginx-lens include-tree /etc/nginx/nginx.conf --directive server_name
|
|
20
20
|
"""
|
|
21
|
-
|
|
21
|
+
try:
|
|
22
|
+
tree = build_include_tree(config_path)
|
|
23
|
+
except FileNotFoundError:
|
|
24
|
+
console.print(f"[red]Файл {config_path} не найден. Проверьте путь к конфигу.[/red]")
|
|
25
|
+
return
|
|
26
|
+
except Exception as e:
|
|
27
|
+
console.print(f"[red]Ошибка при разборе {config_path}: {e}[/red]")
|
|
28
|
+
return
|
|
22
29
|
rich_tree = Tree(f"[bold blue]{config_path}[/bold blue]")
|
|
23
30
|
def _add(node, t):
|
|
24
31
|
for k, v in t.items():
|
commands/route.py
CHANGED
|
@@ -31,8 +31,12 @@ def route(
|
|
|
31
31
|
for conf in configs:
|
|
32
32
|
try:
|
|
33
33
|
tree = parse_nginx_config(conf)
|
|
34
|
+
except FileNotFoundError:
|
|
35
|
+
console.print(f"[red]Файл {conf} не найден. Проверьте путь к конфигу.[/red]")
|
|
36
|
+
continue
|
|
34
37
|
except Exception as e:
|
|
35
|
-
|
|
38
|
+
console.print(f"[red]Ошибка при разборе {conf}: {e}[/red]")
|
|
39
|
+
continue
|
|
36
40
|
res = find_route(tree, url)
|
|
37
41
|
if res:
|
|
38
42
|
server = res['server']
|
commands/syntax.py
CHANGED
|
@@ -33,6 +33,9 @@ def syntax(
|
|
|
33
33
|
if not config_path:
|
|
34
34
|
console.print("[red]Не удалось найти nginx.conf. Укажите путь через -c.[/red]")
|
|
35
35
|
return
|
|
36
|
+
if not os.path.isfile(config_path):
|
|
37
|
+
console.print(f"[red]Файл {config_path} не найден. Проверьте путь к конфигу.[/red]")
|
|
38
|
+
return
|
|
36
39
|
cmd = [nginx_path, "-t", "-c", os.path.abspath(config_path)]
|
|
37
40
|
try:
|
|
38
41
|
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
|
|
@@ -41,8 +44,8 @@ def syntax(
|
|
|
41
44
|
return
|
|
42
45
|
else:
|
|
43
46
|
console.print("[red]Ошибка синтаксиса![/red]")
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
console.print(result.stdout)
|
|
48
|
+
console.print(result.stderr)
|
|
46
49
|
# Парсим все ошибки
|
|
47
50
|
err = result.stderr or result.stdout
|
|
48
51
|
errors = list(ERRORS_RE.finditer(err))
|
commands/tree.py
CHANGED
|
@@ -34,7 +34,14 @@ def tree(
|
|
|
34
34
|
nginx-lens tree /etc/nginx/nginx.conf --markdown
|
|
35
35
|
nginx-lens tree /etc/nginx/nginx.conf --html
|
|
36
36
|
"""
|
|
37
|
-
|
|
37
|
+
try:
|
|
38
|
+
tree_obj = parse_nginx_config(config_path)
|
|
39
|
+
except FileNotFoundError:
|
|
40
|
+
console.print(f"[red]Файл {config_path} не найден. Проверьте путь к конфигу.[/red]")
|
|
41
|
+
return
|
|
42
|
+
except Exception as e:
|
|
43
|
+
console.print(f"[red]Ошибка при разборе {config_path}: {e}[/red]")
|
|
44
|
+
return
|
|
38
45
|
root = RichTree(f"[bold blue]nginx.conf[/bold blue]")
|
|
39
46
|
_build_tree(tree_obj.directives, root)
|
|
40
47
|
if markdown:
|
|
@@ -11,16 +11,16 @@ analyzer/route.py,sha256=2xxQooQEsfn10tzGCZUoP32T0OnTMnPB6qRgBR6not8,2345
|
|
|
11
11
|
analyzer/unused.py,sha256=Ixzv0bPsw9IafblVwLiAOgugdg2dGu1MJDtuoqzPZiY,1066
|
|
12
12
|
analyzer/warnings.py,sha256=zC36QMvegA2eQPvZ-P1eysrX_kXHx5A1MUKHKKNvG5c,5784
|
|
13
13
|
commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
commands/analyze.py,sha256=
|
|
14
|
+
commands/analyze.py,sha256=W6begSgXNjgKJGoGeguR3WKgHPLkClWXxxpDcqvsJdc,8343
|
|
15
15
|
commands/cli.py,sha256=9HwDJ-po5al0ceb4Wkyw5F2wzqxbJTo0CbHQ2AQ8obo,722
|
|
16
|
-
commands/diff.py,sha256=
|
|
17
|
-
commands/graph.py,sha256=
|
|
16
|
+
commands/diff.py,sha256=C7gRIWh6DNWHzjiQBPVTn-rZ40m2KCY75Zd6Q4URJIE,2076
|
|
17
|
+
commands/graph.py,sha256=fvYDUvj_BXdIAm8eg52v5VxhkZijb2YDkCw7D21ZK-M,4650
|
|
18
18
|
commands/health.py,sha256=d2bBui0qauQtO4Ll9cjniKR1Y5dYJBQzG9CECDnsUQ4,1365
|
|
19
|
-
commands/include.py,sha256=
|
|
19
|
+
commands/include.py,sha256=5PTYG5C00-AlWfIgpQXLq9E7C9yTFSv7HrZkM5ogDps,2224
|
|
20
20
|
commands/logs.py,sha256=8tnGsgNy_B97S3O0D_6bvOVfNvAyqeUNotlDOdjltgw,3420
|
|
21
|
-
commands/route.py,sha256=
|
|
22
|
-
commands/syntax.py,sha256=
|
|
23
|
-
commands/tree.py,sha256=
|
|
21
|
+
commands/route.py,sha256=H_xMk9KoqwesutzT9ewiTsakfdjmu01kka9ZQc14faY,2222
|
|
22
|
+
commands/syntax.py,sha256=gABzFvml92bHqYa6YdRx78bmrtd9v2ORT_Hz-gfQu1U,3336
|
|
23
|
+
commands/tree.py,sha256=mDfx0Aeg1EDQSYQoJ2nJIkSd_uP7ZR7pEqy7Cw3clQ0,2161
|
|
24
24
|
exporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
exporter/graph.py,sha256=WYUrqUgCaK6KihgxAcRHaQn4oMo6b7ybC8yb_36ZIsA,3995
|
|
26
26
|
exporter/html.py,sha256=uquEM-WvBt2aV9GshgaI3UVhYd8sD0QQ-OmuNtvYUdU,798
|
|
@@ -29,8 +29,8 @@ parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
29
29
|
parser/nginx_parser.py,sha256=JqZ3clNy4Nf-bmbsx_rJUL7EgRoB79b87eEu_isMeqg,3577
|
|
30
30
|
upstream_checker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
31
|
upstream_checker/checker.py,sha256=9-6CMUTN7gXUACP8EwX722QogfujZyV-WWWUeM3a79k,455
|
|
32
|
-
nginx_lens-0.1.
|
|
33
|
-
nginx_lens-0.1.
|
|
34
|
-
nginx_lens-0.1.
|
|
35
|
-
nginx_lens-0.1.
|
|
36
|
-
nginx_lens-0.1.
|
|
32
|
+
nginx_lens-0.1.6.dist-info/METADATA,sha256=FhO8QQOa9YfJzMUtNq313YcaNQAhHr2UEMNHXDIJkBU,476
|
|
33
|
+
nginx_lens-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
34
|
+
nginx_lens-0.1.6.dist-info/entry_points.txt,sha256=qEcecjSyLqcJjbIVlNlTpqAhPqDyaujUV5ZcBTAr3po,48
|
|
35
|
+
nginx_lens-0.1.6.dist-info/top_level.txt,sha256=mxLJO4rZg0rbixVGhplF3fUNFs8vxDIL25ronZNvRy4,51
|
|
36
|
+
nginx_lens-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|