nginx-lens 0.2.1__tar.gz → 0.2.3__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.
- {nginx_lens-0.2.1/nginx_lens.egg-info → nginx_lens-0.2.3}/PKG-INFO +1 -1
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/README.md +36 -3
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/health.py +9 -4
- {nginx_lens-0.2.1 → nginx_lens-0.2.3/nginx_lens.egg-info}/PKG-INFO +1 -1
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/setup.py +1 -1
- nginx_lens-0.2.3/upstream_checker/checker.py +79 -0
- nginx_lens-0.2.1/upstream_checker/checker.py +0 -12
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/LICENSE +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/__init__.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/base.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/conflicts.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/dead_locations.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/diff.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/duplicates.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/empty_blocks.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/include.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/rewrite.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/route.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/unused.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/analyzer/warnings.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/__init__.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/analyze.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/cli.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/diff.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/graph.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/include.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/logs.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/route.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/syntax.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/commands/tree.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/exporter/__init__.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/exporter/graph.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/exporter/html.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/exporter/markdown.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/nginx_lens.egg-info/SOURCES.txt +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/nginx_lens.egg-info/dependency_links.txt +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/nginx_lens.egg-info/entry_points.txt +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/nginx_lens.egg-info/requires.txt +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/nginx_lens.egg-info/top_level.txt +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/parser/__init__.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/parser/nginx_parser.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/pyproject.toml +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/setup.cfg +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/tests/test_conflicts.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/tests/test_duplicates.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/tests/test_empty_blocks.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/tests/test_health.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/tests/test_parser.py +0 -0
- {nginx_lens-0.2.1 → nginx_lens-0.2.3}/upstream_checker/__init__.py +0 -0
|
@@ -13,46 +13,79 @@
|
|
|
13
13
|
## Примеры работы
|
|
14
14
|
|
|
15
15
|
### Справочник утилиты
|
|
16
|
+
```bash
|
|
17
|
+
nginx-lens --help
|
|
18
|
+
```
|
|
16
19
|
|
|
17
20
|

|
|
18
21
|
|
|
19
22
|
### Справочник для команд
|
|
23
|
+
```bash
|
|
24
|
+
nginx-lens <команда> --help
|
|
25
|
+
```
|
|
20
26
|
|
|
21
27
|

|
|
22
28
|
|
|
23
29
|
### Доступность upstream-серверов
|
|
30
|
+
```bash
|
|
31
|
+
nginx-lens health <путь_к_конфигу>
|
|
32
|
+
```
|
|
24
33
|
|
|
25
34
|

|
|
26
35
|
|
|
27
36
|
### Древовидная визуализация структуры конфига
|
|
37
|
+
```bash
|
|
38
|
+
nginx-lens tree <путь_к_конфигу>
|
|
39
|
+
```
|
|
28
40
|
|
|
29
41
|

|
|
30
42
|
|
|
31
43
|
### Древовидная визуализация include'ов
|
|
44
|
+
```bash
|
|
45
|
+
nginx-lens include-tree <путь_к_конфигу>
|
|
46
|
+
```
|
|
32
47
|
|
|
33
48
|

|
|
34
49
|
|
|
35
50
|
### Удобный анализатор логов
|
|
51
|
+
```bash
|
|
52
|
+
nginx-lens logs <путь_к_файлу_лога>
|
|
53
|
+
```
|
|
36
54
|
|
|
37
55
|

|
|
38
56
|
|
|
39
57
|
### Аудит конфигурации
|
|
58
|
+
```bash
|
|
59
|
+
nginx-lens analyze <путь_к_конфигу>
|
|
60
|
+
```
|
|
40
61
|
|
|
41
62
|

|
|
42
63
|
|
|
43
64
|
### Визуализация маршрутов
|
|
65
|
+
```bash
|
|
66
|
+
nginx-lens graph <путь_к_конфигу>
|
|
67
|
+
```
|
|
44
68
|
|
|
45
69
|

|
|
46
70
|
|
|
47
71
|
### Поиск маршрута для URL
|
|
72
|
+
```bash
|
|
73
|
+
nginx-lens route <URL>
|
|
74
|
+
```
|
|
48
75
|
|
|
49
76
|

|
|
50
77
|
|
|
51
78
|
### Сравнение конфигов
|
|
79
|
+
```bash
|
|
80
|
+
nginx-lens diff <путь_к_первому_конфигу> <путь_к_второму_конфигу>
|
|
81
|
+
```
|
|
52
82
|
|
|
53
83
|

|
|
54
84
|
|
|
55
85
|
### Удобная проверка синтаксиса конфига
|
|
86
|
+
```bash
|
|
87
|
+
nginx-lens syntax
|
|
88
|
+
```
|
|
56
89
|
|
|
57
90
|

|
|
58
91
|
|
|
@@ -65,9 +98,9 @@
|
|
|
65
98
|
### Установка с помощью bash-скрипта (Рекомендуется)
|
|
66
99
|
|
|
67
100
|
```bash
|
|
68
|
-
wget https://raw.githubusercontent.com/shelovesuastra/nginx-lens/install-nginx-lens.sh
|
|
101
|
+
wget https://raw.githubusercontent.com/shelovesuastra/nginx-lens/refs/heads/main/install-nginx-lens.sh
|
|
69
102
|
# или
|
|
70
|
-
curl https://raw.githubusercontent.com/shelovesuastra/nginx-lens/install-nginx-lens.sh
|
|
103
|
+
curl https://raw.githubusercontent.com/shelovesuastra/nginx-lens/refs/heads/main/install-nginx-lens.sh
|
|
71
104
|
|
|
72
105
|
chmod +x install-nginx-lens.sh
|
|
73
106
|
|
|
@@ -94,4 +127,4 @@ pip install nginx-lens
|
|
|
94
127
|
|
|
95
128
|
## Лицензия
|
|
96
129
|
|
|
97
|
-
MIT
|
|
130
|
+
MIT
|
|
@@ -10,14 +10,15 @@ console = Console()
|
|
|
10
10
|
def health(
|
|
11
11
|
config_path: str = typer.Argument(..., help="Путь к nginx.conf"),
|
|
12
12
|
timeout: float = typer.Option(2.0, help="Таймаут проверки (сек)"),
|
|
13
|
-
retries: int = typer.Option(1, help="Количество попыток")
|
|
13
|
+
retries: int = typer.Option(1, help="Количество попыток"),
|
|
14
|
+
mode: str = typer.Option("tcp", help="Режим проверки: tcp или http", case_sensitive=False),
|
|
14
15
|
):
|
|
15
16
|
"""
|
|
16
17
|
Проверяет доступность upstream-серверов, определённых в nginx.conf. Выводит таблицу.
|
|
17
18
|
|
|
18
19
|
Пример:
|
|
19
20
|
nginx-lens health /etc/nginx/nginx.conf
|
|
20
|
-
nginx-lens health /etc/nginx/nginx.conf --timeout 5 --retries 3
|
|
21
|
+
nginx-lens health /etc/nginx/nginx.conf --timeout 5 --retries 3 --mode http
|
|
21
22
|
"""
|
|
22
23
|
try:
|
|
23
24
|
tree = parse_nginx_config(config_path)
|
|
@@ -27,14 +28,18 @@ def health(
|
|
|
27
28
|
except Exception as e:
|
|
28
29
|
console.print(f"[red]Ошибка при разборе {config_path}: {e}[/red]")
|
|
29
30
|
return
|
|
31
|
+
|
|
30
32
|
upstreams = tree.get_upstreams()
|
|
31
|
-
results = check_upstreams(upstreams, timeout=timeout, retries=retries)
|
|
33
|
+
results = check_upstreams(upstreams, timeout=timeout, retries=retries, mode=mode.lower())
|
|
34
|
+
|
|
32
35
|
table = Table(show_header=True, header_style="bold blue")
|
|
33
36
|
table.add_column("upstream_name")
|
|
34
37
|
table.add_column("upstream_status")
|
|
38
|
+
|
|
35
39
|
for name, servers in results.items():
|
|
36
40
|
for srv in servers:
|
|
37
41
|
status = "Healthy" if srv["healthy"] else "Unhealthy"
|
|
38
42
|
color = "green" if srv["healthy"] else "red"
|
|
39
43
|
table.add_row(srv["address"], f"[{color}]{status}[/{color}]")
|
|
40
|
-
|
|
44
|
+
|
|
45
|
+
console.print(table)
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="nginx-lens",
|
|
5
|
-
version="0.2.
|
|
5
|
+
version="0.2.3",
|
|
6
6
|
description="CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx",
|
|
7
7
|
author="Daniil Astrouski",
|
|
8
8
|
author_email="shelovesuastra@gmail.com",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# upstream_checker/checker.py
|
|
2
|
+
|
|
3
|
+
import socket
|
|
4
|
+
import time
|
|
5
|
+
import http.client
|
|
6
|
+
from typing import Dict, List
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def check_tcp(address: str, timeout: float, retries: int) -> bool:
|
|
10
|
+
"""
|
|
11
|
+
Проверка доступности сервера по TCP.
|
|
12
|
+
Ignores extra upstream options like 'max_fails' or 'fail_timeout'.
|
|
13
|
+
"""
|
|
14
|
+
# Берем только host:port, игнорируем параметры
|
|
15
|
+
host_port = address.split()[0]
|
|
16
|
+
host, port = host_port.split(":")
|
|
17
|
+
port = int(port)
|
|
18
|
+
|
|
19
|
+
for _ in range(retries):
|
|
20
|
+
try:
|
|
21
|
+
with socket.create_connection((host, port), timeout=timeout):
|
|
22
|
+
return True
|
|
23
|
+
except (socket.timeout, ConnectionRefusedError, OSError):
|
|
24
|
+
time.sleep(0.2)
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def check_http(address: str, timeout: float, retries: int) -> bool:
|
|
29
|
+
"""
|
|
30
|
+
Проверка доступности сервера по HTTP (GET /).
|
|
31
|
+
Ignores extra upstream options like 'max_fails' or 'fail_timeout'.
|
|
32
|
+
"""
|
|
33
|
+
host_port = address.split()[0]
|
|
34
|
+
host, port = host_port.split(":")
|
|
35
|
+
port = int(port)
|
|
36
|
+
|
|
37
|
+
for _ in range(retries):
|
|
38
|
+
try:
|
|
39
|
+
conn = http.client.HTTPConnection(host, port, timeout=timeout)
|
|
40
|
+
conn.request("GET", "/")
|
|
41
|
+
resp = conn.getresponse()
|
|
42
|
+
healthy = resp.status < 500
|
|
43
|
+
conn.close()
|
|
44
|
+
if healthy:
|
|
45
|
+
return True
|
|
46
|
+
except Exception:
|
|
47
|
+
time.sleep(0.2)
|
|
48
|
+
continue
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def check_upstreams(
|
|
53
|
+
upstreams: Dict[str, List[str]],
|
|
54
|
+
timeout: float = 2.0,
|
|
55
|
+
retries: int = 1,
|
|
56
|
+
mode: str = "tcp"
|
|
57
|
+
) -> Dict[str, List[dict]]:
|
|
58
|
+
"""
|
|
59
|
+
Проверяет доступность upstream-серверов.
|
|
60
|
+
mode: "tcp" (по умолчанию) или "http"
|
|
61
|
+
|
|
62
|
+
Возвращает:
|
|
63
|
+
{
|
|
64
|
+
"backend": [
|
|
65
|
+
{"address": "127.0.0.1:8080", "healthy": True},
|
|
66
|
+
...
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
"""
|
|
70
|
+
results = {}
|
|
71
|
+
for name, servers in upstreams.items():
|
|
72
|
+
results[name] = []
|
|
73
|
+
for srv in servers:
|
|
74
|
+
if mode.lower() == "http":
|
|
75
|
+
healthy = check_http(srv, timeout, retries)
|
|
76
|
+
else:
|
|
77
|
+
healthy = check_tcp(srv, timeout, retries)
|
|
78
|
+
results[name].append({"address": srv, "healthy": healthy})
|
|
79
|
+
return results
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import socket
|
|
2
|
-
from typing import Dict, List
|
|
3
|
-
|
|
4
|
-
def check_upstreams(upstreams: Dict[str, List[str]], timeout=2.0, retries=1):
|
|
5
|
-
# TODO: Реализовать реальную проверку TCP/HTTP
|
|
6
|
-
# Сейчас возвращает все healthy
|
|
7
|
-
result = {}
|
|
8
|
-
for name, servers in upstreams.items():
|
|
9
|
-
result[name] = []
|
|
10
|
-
for srv in servers:
|
|
11
|
-
result[name].append({"address": srv, "healthy": True})
|
|
12
|
-
return result
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|