nginx-lens 0.1.0__tar.gz → 0.1.1__tar.gz

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.
Files changed (40) hide show
  1. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/PKG-INFO +1 -1
  2. nginx_lens-0.1.1/commands/analyze.py +50 -0
  3. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/commands/diff.py +11 -10
  4. nginx_lens-0.1.1/commands/route.py +43 -0
  5. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/nginx_lens.egg-info/PKG-INFO +1 -1
  6. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/setup.py +1 -1
  7. nginx_lens-0.1.0/commands/analyze.py +0 -70
  8. nginx_lens-0.1.0/commands/route.py +0 -30
  9. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/__init__.py +0 -0
  10. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/base.py +0 -0
  11. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/conflicts.py +0 -0
  12. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/diff.py +0 -0
  13. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/duplicates.py +0 -0
  14. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/empty_blocks.py +0 -0
  15. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/route.py +0 -0
  16. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/unused.py +0 -0
  17. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/analyzer/warnings.py +0 -0
  18. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/commands/__init__.py +0 -0
  19. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/commands/cli.py +0 -0
  20. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/commands/health.py +0 -0
  21. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/commands/tree.py +0 -0
  22. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/exporter/__init__.py +0 -0
  23. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/exporter/html.py +0 -0
  24. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/exporter/markdown.py +0 -0
  25. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/nginx_lens.egg-info/SOURCES.txt +0 -0
  26. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/nginx_lens.egg-info/dependency_links.txt +0 -0
  27. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/nginx_lens.egg-info/entry_points.txt +0 -0
  28. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/nginx_lens.egg-info/requires.txt +0 -0
  29. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/nginx_lens.egg-info/top_level.txt +0 -0
  30. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/parser/__init__.py +0 -0
  31. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/parser/nginx_parser.py +0 -0
  32. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/pyproject.toml +0 -0
  33. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/setup.cfg +0 -0
  34. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/tests/test_conflicts.py +0 -0
  35. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/tests/test_duplicates.py +0 -0
  36. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/tests/test_empty_blocks.py +0 -0
  37. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/tests/test_health.py +0 -0
  38. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/tests/test_parser.py +0 -0
  39. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/upstream_checker/__init__.py +0 -0
  40. {nginx_lens-0.1.0 → nginx_lens-0.1.1}/upstream_checker/checker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nginx-lens
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx
5
5
  Author: Daniil Astrouski
6
6
  Author-email: shelovesuastra@gmail.com
@@ -0,0 +1,50 @@
1
+ import typer
2
+ from rich.console import Console
3
+ from rich.table import Table
4
+ from analyzer.conflicts import find_location_conflicts
5
+ from analyzer.duplicates import find_duplicate_directives
6
+ from analyzer.empty_blocks import find_empty_blocks
7
+ from analyzer.warnings import find_warnings
8
+ from analyzer.unused import find_unused_variables
9
+ from parser.nginx_parser import parse_nginx_config
10
+
11
+ app = typer.Typer()
12
+ console = Console()
13
+
14
+ def analyze(config_path: str = typer.Argument(..., help="Путь к nginx.conf")):
15
+ """
16
+ Анализирует конфигурацию Nginx на типовые проблемы. Выводит таблицу issue_type/issue_description.
17
+ """
18
+ tree = parse_nginx_config(config_path)
19
+ conflicts = find_location_conflicts(tree)
20
+ dups = find_duplicate_directives(tree)
21
+ empties = find_empty_blocks(tree)
22
+ warnings = find_warnings(tree)
23
+ unused_vars = find_unused_variables(tree)
24
+
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]")
49
+ else:
50
+ console.print(table)
@@ -1,7 +1,6 @@
1
1
  import typer
2
2
  from rich.console import Console
3
- from rich.tree import Tree
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
- root = Tree("[bold blue]Diff nginx.conf[/bold blue]")
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
- root.add(f"[green]+ {path}[/green]")
29
+ table.add_row("", f"+ {path}")
29
30
  elif d['type'] == 'removed':
30
- root.add(f"[red]- {path}[/red]")
31
+ table.add_row(f"- {path}", "")
31
32
  elif d['type'] == 'changed':
32
- node = root.add(f"[yellow]! {path}[/yellow]")
33
- node.add(f"[red]- {d['value1']}[/red]")
34
- node.add(f"[green]+ {d['value2']}[/green]")
35
- console.print(root)
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)
@@ -0,0 +1,43 @@
1
+ import typer
2
+ from rich.console import Console
3
+ from rich.table import Table
4
+ from analyzer.route import find_route
5
+ from parser.nginx_parser import parse_nginx_config
6
+ from upstream_checker.checker import check_upstreams
7
+
8
+ app = typer.Typer()
9
+ console = Console()
10
+
11
+ def route(
12
+ config_path: str = typer.Argument(..., help="Путь к nginx.conf"),
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="Количество попыток")
16
+ ):
17
+ """
18
+ Показывает, какой server/location обслуживает указанный URL и статус upstream-ов (таблица).
19
+ """
20
+ tree = parse_nginx_config(config_path)
21
+ res = find_route(tree, url)
22
+ if not res:
23
+ console.print("[red]Не найден подходящий server для {url}[/red]")
24
+ return
25
+ server = res['server']
26
+ location = res['location']
27
+ proxy_pass = res['proxy_pass']
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
32
+ if proxy_pass:
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nginx-lens
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx
5
5
  Author: Daniil Astrouski
6
6
  Author-email: shelovesuastra@gmail.com
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="nginx-lens",
5
- version="0.1.0",
5
+ version="0.1.1",
6
6
  description="CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx",
7
7
  author="Daniil Astrouski",
8
8
  author_email="shelovesuastra@gmail.com",
@@ -1,70 +0,0 @@
1
- import typer
2
- from rich.console import Console
3
- from rich.panel import Panel
4
- from rich.tree import Tree
5
- from analyzer.conflicts import find_location_conflicts
6
- from analyzer.duplicates import find_duplicate_directives
7
- from analyzer.empty_blocks import find_empty_blocks
8
- from parser.nginx_parser import parse_nginx_config
9
- from analyzer.warnings import find_warnings
10
- from analyzer.unused import find_unused_variables
11
-
12
- app = typer.Typer()
13
- console = Console()
14
-
15
- def analyze(config_path: str = typer.Argument(..., help="Путь к nginx.conf")):
16
- """
17
- Анализирует конфигурацию Nginx на типовые проблемы.
18
- """
19
- tree = parse_nginx_config(config_path)
20
- conflicts = find_location_conflicts(tree)
21
- dups = find_duplicate_directives(tree)
22
- empties = find_empty_blocks(tree)
23
- warnings = find_warnings(tree)
24
- unused_vars = find_unused_variables(tree)
25
-
26
- root = Tree("[bold blue]Анализ конфигурации Nginx[/bold blue]")
27
-
28
- if conflicts:
29
- node = root.add("[red]Конфликты location-ов[/red]")
30
- for c in conflicts:
31
- node.add(f"[yellow]server[/yellow]: {c['server'].get('arg', '')} [magenta]location[/magenta]: [bold]{c['location1']}[/bold] ↔ [bold]{c['location2']}[/bold]")
32
- else:
33
- root.add("[green]Нет конфликтов location-ов[/green]")
34
-
35
- if dups:
36
- node = root.add("[red]Дублирующиеся директивы[/red]")
37
- for d in dups:
38
- node.add(f"[yellow]{d['directive']}[/yellow] ([italic]{d['args']}[/italic]) — {d['count']} раз в блоке [cyan]{d['block'].get('block', d['block'])}[/cyan]")
39
- else:
40
- root.add("[green]Нет дублирующихся директив[/green]")
41
-
42
- if empties:
43
- node = root.add("[red]Пустые блоки[/red]")
44
- for e in empties:
45
- node.add(f"[yellow]{e['block']}[/yellow] [italic]{e['arg'] or ''}[/italic]")
46
- else:
47
- root.add("[green]Нет пустых блоков[/green]")
48
-
49
- if warnings:
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]")
60
- else:
61
- root.add("[green]Нет потенциальных проблем[/green]")
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)
@@ -1,30 +0,0 @@
1
- import typer
2
- from rich.console import Console
3
- from rich.panel import Panel
4
- from analyzer.route import find_route
5
- from parser.nginx_parser import parse_nginx_config
6
-
7
- app = typer.Typer()
8
- console = Console()
9
-
10
- def route(
11
- config_path: str = typer.Argument(..., help="Путь к nginx.conf"),
12
- url: str = typer.Argument(..., help="URL для маршрутизации (например, http://host/path)")
13
- ):
14
- """
15
- Показывает, какой server/location обслуживает указанный URL.
16
- """
17
- tree = parse_nginx_config(config_path)
18
- res = find_route(tree, url)
19
- if not res:
20
- console.print(Panel(f"Не найден подходящий server для {url}", style="red"))
21
- return
22
- server = res['server']
23
- location = res['location']
24
- proxy_pass = res['proxy_pass']
25
- text = f"[bold]Server:[/bold] {server.get('arg','') or '[no arg]'}\n"
26
- if location:
27
- text += f"[bold]Location:[/bold] {location.get('arg','')}\n"
28
- if proxy_pass:
29
- text += f"[bold]proxy_pass:[/bold] {proxy_pass}\n"
30
- console.print(Panel(text, title="Route", style="green"))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes