nginx-lens 0.3.0__py3-none-any.whl → 0.3.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/health.py CHANGED
@@ -51,15 +51,17 @@ def health(
51
51
  color = "green" if srv["healthy"] else "red"
52
52
 
53
53
  if resolve:
54
- resolved = None
54
+ resolved_list = []
55
55
  if name in resolved_info:
56
56
  for resolved_srv in resolved_info[name]:
57
57
  if resolved_srv["address"] == srv["address"]:
58
- resolved = resolved_srv["resolved"]
58
+ resolved_list = resolved_srv["resolved"]
59
59
  break
60
60
 
61
- if resolved:
62
- table.add_row(srv["address"], f"[{color}]{status}[/{color}]", resolved)
61
+ if resolved_list:
62
+ # Показываем все IP-адреса через запятую
63
+ resolved_str = ", ".join(resolved_list)
64
+ table.add_row(srv["address"], f"[{color}]{status}[/{color}]", f"[green]{resolved_str}[/green]")
63
65
  else:
64
66
  table.add_row(srv["address"], f"[{color}]{status}[/{color}]", "[yellow]Failed to resolve[/yellow]")
65
67
  else:
commands/resolve.py CHANGED
@@ -40,8 +40,11 @@ def resolve(
40
40
  for name, servers in results.items():
41
41
  for idx, srv in enumerate(servers):
42
42
  upstream_name = name if idx == 0 else ""
43
- if srv["resolved"]:
44
- table.add_row(upstream_name, srv["address"], f"[green]{srv['resolved']}[/green]")
43
+ resolved_list = srv["resolved"]
44
+ if resolved_list:
45
+ # Показываем все IP-адреса через запятую
46
+ resolved_str = ", ".join(resolved_list)
47
+ table.add_row(upstream_name, srv["address"], f"[green]{resolved_str}[/green]")
45
48
  else:
46
49
  table.add_row(upstream_name, srv["address"], "[red]Failed to resolve[/red]")
47
50
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nginx-lens
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: CLI-инструмент для анализа, визуализации и диагностики конфигураций Nginx
5
5
  Author: Daniil Astrouski
6
6
  Author-email: shelovesuastra@gmail.com
@@ -15,10 +15,10 @@ commands/analyze.py,sha256=W6begSgXNjgKJGoGeguR3WKgHPLkClWXxxpDcqvsJdc,8343
15
15
  commands/cli.py,sha256=brzp6xDDWIrm7ibaoT4x94hgAdBB2DVWniXoK8dRylE,782
16
16
  commands/diff.py,sha256=C7gRIWh6DNWHzjiQBPVTn-rZ40m2KCY75Zd6Q4URJIE,2076
17
17
  commands/graph.py,sha256=xB6KjXBkLmm5gII3e-5BMRGO7WeTwc7EFxRGzYgnme4,5947
18
- commands/health.py,sha256=Q_eDWrDin-wYzxCCDDfVkQd5VzFjUC0e9I7opGyaSqw,2897
18
+ commands/health.py,sha256=ZGc42Ak4xoZt9r9DJ_84AvgQ8yXCO-CzWppvsOww1Yo,3086
19
19
  commands/include.py,sha256=5PTYG5C00-AlWfIgpQXLq9E7C9yTFSv7HrZkM5ogDps,2224
20
20
  commands/logs.py,sha256=RkPUdIpbO9dOVL56lemreYRuAjMjcqqMxRCKOFv2gC4,3691
21
- commands/resolve.py,sha256=u55MmHRNLIWJpQcPjSOjxtOvsv3Nf0rOQwkh122xyvM,1658
21
+ commands/resolve.py,sha256=hdbvB88bgivNt1v5LMyhf--2mwfI_IUXyi4b1IUB62A,1841
22
22
  commands/route.py,sha256=-x_71u6ENl3iO-oxK3bdE8v5eZKf4xRCydeUyXMFVrY,3163
23
23
  commands/syntax.py,sha256=ZWFdaL8LVv9S694wlk2aV3HJKb0OSKjw3wNgTlNvFR8,3418
24
24
  commands/tree.py,sha256=mDfx0Aeg1EDQSYQoJ2nJIkSd_uP7ZR7pEqy7Cw3clQ0,2161
@@ -26,13 +26,13 @@ exporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  exporter/graph.py,sha256=WYUrqUgCaK6KihgxAcRHaQn4oMo6b7ybC8yb_36ZIsA,3995
27
27
  exporter/html.py,sha256=uquEM-WvBt2aV9GshgaI3UVhYd8sD0QQ-OmuNtvYUdU,798
28
28
  exporter/markdown.py,sha256=_0mXQIhurGEZ0dO-eq9DbsuKNrgEDIblgtL3DAgYNo8,724
29
- nginx_lens-0.3.0.dist-info/licenses/LICENSE,sha256=g8QXKdvZZC56rU8E12vIeYF6R4jeTWOsblOnYAda3K4,1073
29
+ nginx_lens-0.3.1.dist-info/licenses/LICENSE,sha256=g8QXKdvZZC56rU8E12vIeYF6R4jeTWOsblOnYAda3K4,1073
30
30
  parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  parser/nginx_parser.py,sha256=Sa9FtGAkvTqNzoehBvgLUWPJHLLIZYWH9ugSHW50X8s,3699
32
32
  upstream_checker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- upstream_checker/checker.py,sha256=816yjsYlsyjs3B5Xmj7yjU1d-2xesTnMxhCR9WX4tsU,4409
34
- nginx_lens-0.3.0.dist-info/METADATA,sha256=vZFN0kAKjwFK9LBeX0U6MjPXtx7l-e7E7CJIEXn_tE0,520
35
- nginx_lens-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- nginx_lens-0.3.0.dist-info/entry_points.txt,sha256=qEcecjSyLqcJjbIVlNlTpqAhPqDyaujUV5ZcBTAr3po,48
37
- nginx_lens-0.3.0.dist-info/top_level.txt,sha256=mxLJO4rZg0rbixVGhplF3fUNFs8vxDIL25ronZNvRy4,51
38
- nginx_lens-0.3.0.dist-info/RECORD,,
33
+ upstream_checker/checker.py,sha256=Th49U6OF-egTH145XOyrfIUUHtygBJiOtqqD9ZT1lKo,5261
34
+ nginx_lens-0.3.1.dist-info/METADATA,sha256=Z-8Ke06GaHt1iVb4zvhX5G3RiJMHwW7bdHRuwKi9Wd8,520
35
+ nginx_lens-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ nginx_lens-0.3.1.dist-info/entry_points.txt,sha256=qEcecjSyLqcJjbIVlNlTpqAhPqDyaujUV5ZcBTAr3po,48
37
+ nginx_lens-0.3.1.dist-info/top_level.txt,sha256=mxLJO4rZg0rbixVGhplF3fUNFs8vxDIL25ronZNvRy4,51
38
+ nginx_lens-0.3.1.dist-info/RECORD,,
@@ -3,7 +3,7 @@
3
3
  import socket
4
4
  import time
5
5
  import http.client
6
- from typing import Dict, List, Optional
6
+ from typing import Dict, List
7
7
 
8
8
 
9
9
  def check_tcp(address: str, timeout: float, retries: int) -> bool:
@@ -49,48 +49,61 @@ def check_http(address: str, timeout: float, retries: int) -> bool:
49
49
  return False
50
50
 
51
51
 
52
- def resolve_address(address: str) -> Optional[str]:
52
+ def resolve_address(address: str) -> List[str]:
53
53
  """
54
- Резолвит адрес upstream сервера в IP-адрес.
54
+ Резолвит адрес upstream сервера в IP-адреса.
55
55
 
56
56
  Args:
57
57
  address: Адрес в формате "host:port" или "host:port параметры"
58
58
 
59
59
  Returns:
60
- IP-адрес в формате "ip:port" или None, если резолвинг не удался
60
+ Список IP-адресов в формате "ip:port" или пустой список, если резолвинг не удался
61
61
  """
62
62
  try:
63
63
  host_port = address.split()[0]
64
64
 
65
65
  if ":" not in host_port:
66
- return None
66
+ return []
67
67
 
68
68
  parts = host_port.rsplit(":", 1)
69
69
  if len(parts) != 2:
70
- return None
70
+ return []
71
71
  host, port = parts
72
72
 
73
+ # Если это уже IPv4 адрес, возвращаем как есть
73
74
  try:
74
75
  socket.inet_aton(host)
75
- return host_port
76
+ return [host_port]
76
77
  except socket.error:
77
78
  pass
78
79
 
80
+ # Проверяем IPv6 (в квадратных скобках)
79
81
  if host.startswith("[") and host.endswith("]"):
80
82
  ipv6_host = host[1:-1]
81
83
  try:
82
84
  socket.inet_pton(socket.AF_INET6, ipv6_host)
83
- return host_port
85
+ return [host_port]
84
86
  except (socket.error, OSError):
85
87
  pass
86
88
 
89
+ # Пытаемся резолвить DNS имя - получаем все IP-адреса
87
90
  try:
88
- ip = socket.gethostbyname(host)
89
- return f"{ip}:{port}"
91
+ # gethostbyname_ex возвращает (hostname, aliaslist, ipaddrlist)
92
+ _, _, ipaddrlist = socket.gethostbyname_ex(host)
93
+ # Фильтруем только IPv4 адреса (IPv6 обрабатываются отдельно)
94
+ resolved_ips = []
95
+ for ip in ipaddrlist:
96
+ try:
97
+ # Проверяем, что это IPv4
98
+ socket.inet_aton(ip)
99
+ resolved_ips.append(f"{ip}:{port}")
100
+ except socket.error:
101
+ pass
102
+ return resolved_ips if resolved_ips else []
90
103
  except (socket.gaierror, OSError):
91
- return None
104
+ return []
92
105
  except (ValueError, IndexError, AttributeError):
93
- return None
106
+ return []
94
107
 
95
108
 
96
109
  def resolve_upstreams(
@@ -102,9 +115,9 @@ def resolve_upstreams(
102
115
  Возвращает:
103
116
  {
104
117
  "backend": [
105
- {"address": "example.com:8080", "resolved": "192.168.1.1:8080"},
106
- {"address": "127.0.0.1:8080", "resolved": "127.0.0.1:8080"},
107
- {"address": "badhost:80", "resolved": None},
118
+ {"address": "example.com:8080", "resolved": ["192.168.1.1:8080", "192.168.1.2:8080"]},
119
+ {"address": "127.0.0.1:8080", "resolved": ["127.0.0.1:8080"]},
120
+ {"address": "badhost:80", "resolved": []},
108
121
  ...
109
122
  ]
110
123
  }