nginx-lens 0.1.7__tar.gz → 0.1.9__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 (48) hide show
  1. {nginx_lens-0.1.7/nginx_lens.egg-info → nginx_lens-0.1.9}/PKG-INFO +1 -1
  2. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/README.md +17 -1
  3. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/graph.py +25 -5
  4. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/route.py +11 -3
  5. {nginx_lens-0.1.7 → nginx_lens-0.1.9/nginx_lens.egg-info}/PKG-INFO +1 -1
  6. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/parser/nginx_parser.py +7 -7
  7. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/setup.py +1 -1
  8. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/LICENSE +0 -0
  9. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/__init__.py +0 -0
  10. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/base.py +0 -0
  11. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/conflicts.py +0 -0
  12. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/dead_locations.py +0 -0
  13. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/diff.py +0 -0
  14. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/duplicates.py +0 -0
  15. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/empty_blocks.py +0 -0
  16. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/include.py +0 -0
  17. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/rewrite.py +0 -0
  18. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/route.py +0 -0
  19. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/unused.py +0 -0
  20. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/analyzer/warnings.py +0 -0
  21. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/__init__.py +0 -0
  22. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/analyze.py +0 -0
  23. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/cli.py +0 -0
  24. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/diff.py +0 -0
  25. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/health.py +0 -0
  26. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/include.py +0 -0
  27. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/logs.py +0 -0
  28. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/syntax.py +0 -0
  29. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/commands/tree.py +0 -0
  30. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/exporter/__init__.py +0 -0
  31. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/exporter/graph.py +0 -0
  32. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/exporter/html.py +0 -0
  33. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/exporter/markdown.py +0 -0
  34. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/nginx_lens.egg-info/SOURCES.txt +0 -0
  35. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/nginx_lens.egg-info/dependency_links.txt +0 -0
  36. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/nginx_lens.egg-info/entry_points.txt +0 -0
  37. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/nginx_lens.egg-info/requires.txt +0 -0
  38. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/nginx_lens.egg-info/top_level.txt +0 -0
  39. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/parser/__init__.py +0 -0
  40. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/pyproject.toml +0 -0
  41. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/setup.cfg +0 -0
  42. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/tests/test_conflicts.py +0 -0
  43. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/tests/test_duplicates.py +0 -0
  44. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/tests/test_empty_blocks.py +0 -0
  45. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/tests/test_health.py +0 -0
  46. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/tests/test_parser.py +0 -0
  47. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/upstream_checker/__init__.py +0 -0
  48. {nginx_lens-0.1.7 → nginx_lens-0.1.9}/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.7
3
+ Version: 0.1.9
4
4
  Summary: CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx
5
5
  Author: Daniil Astrouski
6
6
  Author-email: shelovesuastra@gmail.com
@@ -62,7 +62,23 @@
62
62
  - **Python 3.8+**
63
63
  - Linux/macOS (работает и под Windows WSL)
64
64
 
65
- ### Установка через PyPI (рекомендуется)
65
+ ### Установка с помощью bash-скрипта (Рекомендуется)
66
+
67
+ ```bash
68
+ wget https://raw.githubusercontent.com/shelovesuastra/nginx-lens/install-nginx-lens.sh
69
+ # или
70
+ curl https://raw.githubusercontent.com/shelovesuastra/nginx-lens/install-nginx-lens.sh
71
+
72
+ chmod +x install-nginx-lens.sh
73
+
74
+ ./install-nginx-lens.sh
75
+ # или
76
+ sh ./install-nginx-lens.sh
77
+ # или
78
+ bash ./install-nginx-lens.sh
79
+ ```
80
+
81
+ ### Установка через PyPI
66
82
 
67
83
  ```bash
68
84
  pipx install nginx-lens
@@ -3,6 +3,7 @@ from rich.console import Console
3
3
  from parser.nginx_parser import parse_nginx_config
4
4
  from exporter.graph import tree_to_dot, tree_to_mermaid
5
5
  from rich.text import Text
6
+ import os
6
7
 
7
8
  app = typer.Typer()
8
9
  console = Console()
@@ -28,9 +29,8 @@ def graph(
28
29
  # Для каждого server/location строим маршрут
29
30
  def walk(d, chain, upstreams):
30
31
  if d.get('block') == 'server':
31
- srv = d.get('arg','') or '[no arg]'
32
32
  for sub in d.get('directives', []):
33
- walk(sub, chain + [('server', srv)], upstreams)
33
+ walk(sub, chain + [('server', None)], upstreams)
34
34
  elif d.get('block') == 'location':
35
35
  loc = d.get('arg','')
36
36
  for sub in d.get('directives', []):
@@ -65,6 +65,7 @@ def graph(
65
65
  if not routes:
66
66
  console.print("[yellow]Не найдено ни одного маршрута[/yellow]")
67
67
  return
68
+ main_file = os.path.abspath(config_path)
68
69
  # Красивый вывод
69
70
  seen = set()
70
71
  for route in routes:
@@ -78,25 +79,44 @@ def graph(
78
79
  # Получаем label для server
79
80
  server_val = route[0][1]
80
81
  server_block = None
81
- # Найти сам блок server по arg
82
82
  for d in tree.directives:
83
- 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))):
83
+ if d.get('block') == 'server':
84
84
  server_block = d
85
85
  break
86
- label = get_server_label(server_block) if server_block else (server_val or 'default')
86
+ label = get_server_label(server_block) if server_block else 'default'
87
+ server_file = server_block.get('__file__') if server_block else None
87
88
  t.append(f"[", style="white")
88
89
  t.append(f"server: {label}", style="bold blue")
90
+ if server_file and os.path.abspath(server_file) != main_file:
91
+ t.append(f" ({server_file})", style="grey50")
89
92
  t.append("]", style="white")
90
93
  for i, (typ, val) in enumerate(route[1:]):
94
+ block = None
95
+ if typ == 'location' and server_block:
96
+ # Найти location-блок внутри server
97
+ for sub in server_block.get('directives', []):
98
+ if sub.get('block') == 'location' and sub.get('arg') == val:
99
+ block = sub
100
+ break
101
+ elif typ == 'upstream':
102
+ # Найти upstream-блок
103
+ for d in tree.directives:
104
+ if d.get('upstream') == val:
105
+ block = d
106
+ break
91
107
  if typ == 'location':
92
108
  t.append(f" -> [", style="white")
93
109
  t.append(f"location: {val}", style="yellow")
110
+ if block and block.get('__file__') and os.path.abspath(block['__file__']) != main_file:
111
+ t.append(f" ({block['__file__']})", style="grey50")
94
112
  t.append("]", style="white")
95
113
  elif typ == 'proxy_pass':
96
114
  t.append(f" -> proxy_pass: {val}", style="green")
97
115
  elif typ == 'upstream':
98
116
  t.append(f" -> [", style="white")
99
117
  t.append(f"upstream: {val}", style="magenta")
118
+ if block and block.get('__file__') and os.path.abspath(block['__file__']) != main_file:
119
+ t.append(f" ({block['__file__']})", style="grey50")
100
120
  t.append("]", style="white")
101
121
  elif typ == 'upstream_server':
102
122
  t.append(f" -> [", style="white")
@@ -46,11 +46,19 @@ def route(
46
46
  location = res['location']
47
47
  proxy_pass = res['proxy_pass']
48
48
  text = f"[bold]Config:[/bold] {conf}\n"
49
- text += f"[bold]Server:[/bold] {server.get('arg','') or '[no arg]'}\n"
49
+ if server:
50
+ text += f"[bold]Server:[/bold] {server.get('arg','') or '[no arg]'}"
51
+ if server.get('__file__'):
52
+ text += f" ([dim]{server.get('__file__')}[/dim])"
53
+ text += "\n"
50
54
  if location:
51
- text += f"[bold]Location:[/bold] {location.get('arg','')}\n"
55
+ text += f"[bold]Location:[/bold] {location.get('arg','')}"
56
+ if location.get('__file__'):
57
+ text += f" ([dim]{location.get('__file__')}[/dim])"
58
+ text += "\n"
52
59
  if proxy_pass:
53
60
  text += f"[bold]proxy_pass:[/bold] {proxy_pass}\n"
54
61
  console.print(Panel(text, title="Route", style="green"))
55
62
  return
56
- console.print(Panel(f"Ни один ваш конфиг в /etc/nginx не обрабатывает этот URL", style="red"))
63
+ search_dir = os.path.dirname(configs[0]) if configs else '/etc/nginx'
64
+ console.print(Panel(f"Маршрут для {url} не найден ни в одном .conf в {search_dir}", style="yellow"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nginx-lens
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx
5
5
  Author: Daniil Astrouski
6
6
  Author-email: shelovesuastra@gmail.com
@@ -14,7 +14,7 @@ class NginxConfigTree:
14
14
  def _strip_comments(line: str) -> str:
15
15
  return line.split('#', 1)[0].strip()
16
16
 
17
- def _parse_block(lines, base_dir) -> (List[Any], Dict[str, List[str]]):
17
+ def _parse_block(lines, base_dir, source_file=None) -> (List[Any], Dict[str, List[str]]):
18
18
  directives = []
19
19
  upstreams = {}
20
20
  i = 0
@@ -29,7 +29,7 @@ def _parse_block(lines, base_dir) -> (List[Any], Dict[str, List[str]]):
29
29
  for inc_path in glob.glob(pattern):
30
30
  with open(inc_path) as f:
31
31
  inc_lines = f.readlines()
32
- inc_directives, inc_upstreams = _parse_block(inc_lines, os.path.dirname(inc_path))
32
+ inc_directives, inc_upstreams = _parse_block(inc_lines, os.path.dirname(inc_path), inc_path)
33
33
  directives.extend(inc_directives)
34
34
  for k, v in inc_upstreams.items():
35
35
  upstreams.setdefault(k, []).extend(v)
@@ -56,7 +56,7 @@ def _parse_block(lines, base_dir) -> (List[Any], Dict[str, List[str]]):
56
56
  if m_srv:
57
57
  servers.append(m_srv.group(1).strip())
58
58
  upstreams[name] = servers
59
- directives.append({'upstream': name, 'servers': servers})
59
+ directives.append({'upstream': name, 'servers': servers, '__file__': source_file})
60
60
  continue
61
61
  # Блоки (например, server, http, location)
62
62
  m = re.match(r'(\S+)\s*(\S+)?\s*{', line)
@@ -75,15 +75,15 @@ def _parse_block(lines, base_dir) -> (List[Any], Dict[str, List[str]]):
75
75
  if depth > 0:
76
76
  block_lines.append(l)
77
77
  i += 1
78
- sub_directives, sub_upstreams = _parse_block(block_lines, base_dir)
79
- directives.append({'block': block_name, 'arg': block_arg, 'directives': sub_directives})
78
+ sub_directives, sub_upstreams = _parse_block(block_lines, base_dir, source_file)
79
+ directives.append({'block': block_name, 'arg': block_arg, 'directives': sub_directives, '__file__': source_file})
80
80
  for k, v in sub_upstreams.items():
81
81
  upstreams.setdefault(k, []).extend(v)
82
82
  continue
83
83
  # Обычная директива
84
84
  m = re.match(r'(\S+)\s+([^;]+);', line)
85
85
  if m:
86
- directives.append({'directive': m.group(1), 'args': m.group(2)})
86
+ directives.append({'directive': m.group(1), 'args': m.group(2), '__file__': source_file})
87
87
  i += 1
88
88
  return directives, upstreams
89
89
 
@@ -91,5 +91,5 @@ def parse_nginx_config(path: str) -> NginxConfigTree:
91
91
  base_dir = os.path.dirname(os.path.abspath(path))
92
92
  with open(path) as f:
93
93
  lines = f.readlines()
94
- directives, upstreams = _parse_block(lines, base_dir)
94
+ directives, upstreams = _parse_block(lines, base_dir, path)
95
95
  return NginxConfigTree(directives, upstreams)
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="nginx-lens",
5
- version="0.1.7",
5
+ version="0.1.9",
6
6
  description="CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx",
7
7
  author="Daniil Astrouski",
8
8
  author_email="shelovesuastra@gmail.com",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes