netdiag-cli 0.1.0__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.
- netdiag_cli-0.1.0/.gitignore +13 -0
- netdiag_cli-0.1.0/CHANGELOG.md +33 -0
- netdiag_cli-0.1.0/CONTRIBUTING.md +61 -0
- netdiag_cli-0.1.0/LICENSE +21 -0
- netdiag_cli-0.1.0/PKG-INFO +203 -0
- netdiag_cli-0.1.0/README.md +172 -0
- netdiag_cli-0.1.0/docs/CLI_CONTRACT.md +103 -0
- netdiag_cli-0.1.0/docs/README.md +29 -0
- netdiag_cli-0.1.0/docs/config.example.toml +21 -0
- netdiag_cli-0.1.0/docs/cookbook.md +329 -0
- netdiag_cli-0.1.0/netdiag/__init__.py +6 -0
- netdiag_cli-0.1.0/netdiag/banner.py +37 -0
- netdiag_cli-0.1.0/netdiag/cli.py +1260 -0
- netdiag_cli-0.1.0/netdiag/compare_targets.py +36 -0
- netdiag_cli-0.1.0/netdiag/completion.py +115 -0
- netdiag_cli-0.1.0/netdiag/config.py +34 -0
- netdiag_cli-0.1.0/netdiag/display.py +343 -0
- netdiag_cli-0.1.0/netdiag/dns_all.py +45 -0
- netdiag_cli-0.1.0/netdiag/dns_config.py +126 -0
- netdiag_cli-0.1.0/netdiag/dns_tools.py +122 -0
- netdiag_cli-0.1.0/netdiag/doctor.py +140 -0
- netdiag_cli-0.1.0/netdiag/enrichment.py +256 -0
- netdiag_cli-0.1.0/netdiag/exit_codes.py +15 -0
- netdiag_cli-0.1.0/netdiag/health_check.py +97 -0
- netdiag_cli-0.1.0/netdiag/host_info.py +331 -0
- netdiag_cli-0.1.0/netdiag/http_extras.py +216 -0
- netdiag_cli-0.1.0/netdiag/http_probe.py +328 -0
- netdiag_cli-0.1.0/netdiag/info.py +66 -0
- netdiag_cli-0.1.0/netdiag/ipcalc.py +96 -0
- netdiag_cli-0.1.0/netdiag/json_out.py +30 -0
- netdiag_cli-0.1.0/netdiag/latency_probe.py +83 -0
- netdiag_cli-0.1.0/netdiag/models.py +55 -0
- netdiag_cli-0.1.0/netdiag/oncall.py +272 -0
- netdiag_cli-0.1.0/netdiag/port_scan.py +116 -0
- netdiag_cli-0.1.0/netdiag/presets.py +92 -0
- netdiag_cli-0.1.0/netdiag/serialize.py +54 -0
- netdiag_cli-0.1.0/netdiag/speed.py +485 -0
- netdiag_cli-0.1.0/netdiag/ssl_ctx.py +66 -0
- netdiag_cli-0.1.0/netdiag/stats.py +152 -0
- netdiag_cli-0.1.0/netdiag/targets.py +72 -0
- netdiag_cli-0.1.0/netdiag/tools.py +69 -0
- netdiag_cli-0.1.0/netdiag/traceroute.py +169 -0
- netdiag_cli-0.1.0/netdiag/vpn_diag.py +184 -0
- netdiag_cli-0.1.0/pyproject.toml +67 -0
- netdiag_cli-0.1.0/tests/fixtures/dig_short_a.txt +1 -0
- netdiag_cli-0.1.0/tests/fixtures/dig_trace_snippet.txt +7 -0
- netdiag_cli-0.1.0/tests/fixtures/ping_linux.txt +8 -0
- netdiag_cli-0.1.0/tests/fixtures/ping_macos.txt +8 -0
- netdiag_cli-0.1.0/tests/fixtures/traceroute_linux.txt +4 -0
- netdiag_cli-0.1.0/tests/fixtures/traceroute_macos.txt +5 -0
- netdiag_cli-0.1.0/tests/helpers.py +9 -0
- netdiag_cli-0.1.0/tests/test_banner.py +24 -0
- netdiag_cli-0.1.0/tests/test_cli.py +24 -0
- netdiag_cli-0.1.0/tests/test_cli_smoke.py +60 -0
- netdiag_cli-0.1.0/tests/test_config.py +29 -0
- netdiag_cli-0.1.0/tests/test_dns_compare.py +23 -0
- netdiag_cli-0.1.0/tests/test_dns_tools.py +19 -0
- netdiag_cli-0.1.0/tests/test_enrichment.py +10 -0
- netdiag_cli-0.1.0/tests/test_fixtures.py +80 -0
- netdiag_cli-0.1.0/tests/test_http_probe.py +37 -0
- netdiag_cli-0.1.0/tests/test_info.py +31 -0
- netdiag_cli-0.1.0/tests/test_ipcalc.py +41 -0
- netdiag_cli-0.1.0/tests/test_oncall.py +77 -0
- netdiag_cli-0.1.0/tests/test_parse.py +26 -0
- netdiag_cli-0.1.0/tests/test_port_scan.py +38 -0
- netdiag_cli-0.1.0/tests/test_presets.py +29 -0
- netdiag_cli-0.1.0/tests/test_speed.py +67 -0
- netdiag_cli-0.1.0/tests/test_ssl_ctx.py +34 -0
- netdiag_cli-0.1.0/tests/test_stats.py +37 -0
- netdiag_cli-0.1.0/tests/test_targets.py +40 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here.
|
|
4
|
+
|
|
5
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
_No changes yet._
|
|
11
|
+
|
|
12
|
+
## [0.1.0] - 2025-06-04
|
|
13
|
+
|
|
14
|
+
### Initial release
|
|
15
|
+
|
|
16
|
+
**netdiag** is a new stdlib-only CLI for SRE and on-call network troubleshooting - one tool for incident triage instead of stitching together `dig`, `ping`, `curl`, and `traceroute` scripts.
|
|
17
|
+
|
|
18
|
+
**What ships in 0.1.0**
|
|
19
|
+
|
|
20
|
+
- Runbook workflow: `doctor` → `oncall` → `report`, with stable exit codes (`0` / `1` / `2`) for automation
|
|
21
|
+
- Layered probes: traceroute (ASN/BGP enrichment), ping, latency, DNS, TCP ports, HTTP/TLS, redirects, headers
|
|
22
|
+
- Presets for common roles: `web`, `api`, `vpn`, `oncall`
|
|
23
|
+
- VPN diagnostics: tunnel interfaces, routes, resolver drift, corp vs public reachability
|
|
24
|
+
- Throughput smoke test via `speed` (Cloudflare CDN)
|
|
25
|
+
- `--json` on every command; optional `~/.config/netdiag/config.toml`
|
|
26
|
+
- Shell completions (bash / zsh); `netdiag --info` for version and environment
|
|
27
|
+
- Documentation: [README](README.md), [CLI contract](docs/CLI_CONTRACT.md), [cookbook](docs/cookbook.md), CONTRIBUTING, SECURITY
|
|
28
|
+
- CI on Ubuntu and macOS (Python 3.11–3.13); 95+ tests with offline fixtures
|
|
29
|
+
|
|
30
|
+
Install from source or Git - see [README](README.md#install).
|
|
31
|
+
|
|
32
|
+
[Unreleased]: https://github.com/akintunero/netdiag/compare/v0.1.0...HEAD
|
|
33
|
+
[0.1.0]: https://github.com/akintunero/netdiag/releases/tag/v0.1.0
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Contributing to netdiag
|
|
2
|
+
|
|
3
|
+
Thanks for helping build a CLI operators reach for during incidents.
|
|
4
|
+
|
|
5
|
+
## Principles
|
|
6
|
+
|
|
7
|
+
- **Zero runtime PyPI dependencies** - probes wrap system tools and the stdlib
|
|
8
|
+
- **Predictable CLI** - exit codes `0` / `1` / `2`, documented in [docs/CLI_CONTRACT.md](docs/CLI_CONTRACT.md)
|
|
9
|
+
- **Incident-friendly JSON** - new commands should support `--json`
|
|
10
|
+
|
|
11
|
+
## Development setup
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/akintunero/netdiag.git
|
|
15
|
+
cd netdiag
|
|
16
|
+
python3 -m pip install -e ".[dev]"
|
|
17
|
+
pytest -q
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Optional full CLI smoke (requires network):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
bash scripts/cli_smoke.sh
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Good first contributions
|
|
27
|
+
|
|
28
|
+
- Parser tests using fixtures under `tests/fixtures/` (ping, traceroute, `dig`)
|
|
29
|
+
- Additional cookbook entries in [docs/cookbook.md](docs/cookbook.md)
|
|
30
|
+
- Platform notes (macOS vs Linux tool paths and flags)
|
|
31
|
+
- Clearer errors when `dig`, `traceroute`, or `ping` is missing
|
|
32
|
+
- Probes that do not add required dependencies to `pyproject.toml`
|
|
33
|
+
|
|
34
|
+
For larger features, open an issue first with the on-call or VPN use case.
|
|
35
|
+
|
|
36
|
+
## Pull request checklist
|
|
37
|
+
|
|
38
|
+
- [ ] `pytest -q` passes
|
|
39
|
+
- [ ] New behavior has tests (fixtures preferred over live network)
|
|
40
|
+
- [ ] README or [docs/](docs/) updated for new commands or flags
|
|
41
|
+
- [ ] No new **required** runtime dependencies in `pyproject.toml`
|
|
42
|
+
- [ ] Scanning or probing commands note authorized-use expectations
|
|
43
|
+
|
|
44
|
+
## Code conventions
|
|
45
|
+
|
|
46
|
+
- Keep `cli.py` handlers thin; logic lives in `netdiag/` modules
|
|
47
|
+
- Use dataclasses for structured results; emit JSON via existing helpers
|
|
48
|
+
- Errors on stderr (`error:` prefix); respect exit codes in `exit_codes.py`
|
|
49
|
+
- Handle missing binaries with actionable messages, not tracebacks
|
|
50
|
+
|
|
51
|
+
## Security
|
|
52
|
+
|
|
53
|
+
See [SECURITY.md](SECURITY.md). Do not commit API keys or internal hostnames in fixtures. Report vulnerabilities privately before public issues.
|
|
54
|
+
|
|
55
|
+
## Releases (maintainers)
|
|
56
|
+
|
|
57
|
+
1. Bump `version` in `pyproject.toml` and `netdiag/__init__.py`
|
|
58
|
+
2. Update [CHANGELOG.md](CHANGELOG.md)
|
|
59
|
+
3. `python -m build && python -m twine check dist/*`
|
|
60
|
+
4. Upload to PyPI: `python3 -m twine upload dist/*` (project name `netdiag-cli`)
|
|
61
|
+
5. Tag the release on GitHub
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Olúmáyòwá Akinkuehinmi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: netdiag-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: One CLI for network troubleshooting: traceroute with BGP/ASN, DNS, latency, VPN checks, and SRE on-call presets.
|
|
5
|
+
Project-URL: Homepage, https://github.com/akintunero/netdiag
|
|
6
|
+
Project-URL: Documentation, https://github.com/akintunero/netdiag#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/akintunero/netdiag
|
|
8
|
+
Project-URL: Issues, https://github.com/akintunero/netdiag/issues
|
|
9
|
+
Author-email: Olúmáyòwá Akinkuehinmi <akintunero101@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: bgp,cli,devtools,dns,network,ping,sre,traceroute,vpn
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: System Administrators
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: System :: Networking
|
|
24
|
+
Classifier: Topic :: System :: Networking :: Monitoring
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# netdiag
|
|
33
|
+
|
|
34
|
+
**Production runbook CLI for network incidents** - traceroute with ASN/BGP, DNS drift, latency, VPN checks, and on-call presets in one binary.
|
|
35
|
+
|
|
36
|
+
[](https://github.com/akintunero/netdiag/actions/workflows/ci.yml)
|
|
37
|
+

|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
**Stdlib-only at runtime** · **`--json` on every command** · **Exit codes built for automation**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
netdiag doctor
|
|
44
|
+
netdiag oncall <HOST> --json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
| Method | Command |
|
|
52
|
+
|--------|---------|
|
|
53
|
+
| From source (dev) | `python3 -m pip install -e ".[dev]"` |
|
|
54
|
+
| PyPI | `python3 -m pip install netdiag-cli` |
|
|
55
|
+
| From Git | `python3 -m pip install "git+https://github.com/akintunero/netdiag.git"` |
|
|
56
|
+
|
|
57
|
+
Use `python3 -m pip` (not bare `pip`) on macOS if `pip` is missing. The PyPI package is **`netdiag-cli`**; the command is still **`netdiag`**.
|
|
58
|
+
|
|
59
|
+
**System tools:** `ping` (required), plus `traceroute`, `dig`, and routing/socket tools as needed. Run `netdiag doctor` to see what is on your PATH.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Runbook workflow
|
|
64
|
+
|
|
65
|
+
| Step | Command | Exit code |
|
|
66
|
+
|------|---------|-----------|
|
|
67
|
+
| 1. Pre-flight | `netdiag doctor` | `0` ready · `2` missing required tools |
|
|
68
|
+
| 2. Incident check | `netdiag oncall <HOST> --json` | `0` pass · `1` fail · `2` error |
|
|
69
|
+
| 3. Ticket artifact | `netdiag report <HOST> -o incident.md` | same |
|
|
70
|
+
|
|
71
|
+
Exit code semantics are stable in v0.x - see [docs/CLI_CONTRACT.md](docs/CLI_CONTRACT.md).
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
netdiag oncall 1.1.1.1 --json
|
|
75
|
+
netdiag oncall YOUR-SERVICE.example.com --json | jq '.steps[] | select(.ok==false)'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
> **Tip:** Run one command per line. Do not paste trailing `#` comments from docs into zsh/bash.
|
|
79
|
+
|
|
80
|
+
### VPN and corporate DNS
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
netdiag vpn --corp intranet.company.com
|
|
84
|
+
netdiag oncall app.internal --corp app.internal --vpn --json
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Optional config
|
|
88
|
+
|
|
89
|
+
Copy [docs/config.example.toml](docs/config.example.toml) to `~/.config/netdiag/config.toml`:
|
|
90
|
+
|
|
91
|
+
```toml
|
|
92
|
+
[defaults]
|
|
93
|
+
corp_host = "app.internal.corp"
|
|
94
|
+
|
|
95
|
+
[oncall]
|
|
96
|
+
preset = "oncall"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Shell completions
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
eval "$(netdiag completion bash)"
|
|
103
|
+
eval "$(netdiag completion zsh)"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### About the CLI
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
netdiag --info # version, platform, repo links, wordmark banner
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Set `NETDIAG_NO_BANNER=1` to hide the banner.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Why operators use it
|
|
117
|
+
|
|
118
|
+
| | |
|
|
119
|
+
|---|---|
|
|
120
|
+
| **One CLI** | Replaces ad-hoc `dig` + `ping` + `curl` + `traceroute` scripts |
|
|
121
|
+
| **`--json`** | PagerDuty, CI, Slack bots, `jq` filters |
|
|
122
|
+
| **Presets** | `web`, `api`, `vpn`, `oncall` - tuned check bundles |
|
|
123
|
+
| **Small runtime** | No required PyPI dependencies |
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Quick start (developers)
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git clone https://github.com/akintunero/netdiag.git
|
|
131
|
+
cd netdiag
|
|
132
|
+
python3 -m pip install -e ".[dev]"
|
|
133
|
+
netdiag doctor
|
|
134
|
+
python3 -m pytest tests/ -q
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Smoke test (live network, all subcommands):
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
bash scripts/cli_smoke.sh
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Example probes:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
netdiag oncall 1.1.1.1 --json
|
|
147
|
+
netdiag oncall 1.1.1.1 --preset api --json
|
|
148
|
+
netdiag trace 8.8.8.8 -m 12 --no-bgp-api
|
|
149
|
+
netdiag report 1.1.1.1 -o incident.md
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Command reference
|
|
155
|
+
|
|
156
|
+
| Command | Description |
|
|
157
|
+
|---------|-------------|
|
|
158
|
+
| **`doctor`** | Pre-flight: required tools for runbooks |
|
|
159
|
+
| **`oncall`** | Primary incident bundle (preset `oncall`) |
|
|
160
|
+
| `report` | Markdown report (`-o file.md`, `--vpn`) |
|
|
161
|
+
| `vpn` | VPN, split-tunnel, DNS drift |
|
|
162
|
+
| `check` | Health check; `--preset` for bundles |
|
|
163
|
+
| `trace` | Traceroute + ASN/BGP enrichment |
|
|
164
|
+
| `ping` / `latency` | RTT, jitter, percentiles |
|
|
165
|
+
| `dns` / `dns-trace` / `dns-compare` / `dns-all` | DNS tooling |
|
|
166
|
+
| `port` / `ports` | TCP probes and scans |
|
|
167
|
+
| `http` / `tls` / `redirects` / `headers` | Application layer |
|
|
168
|
+
| `speed` | CDN throughput (Cloudflare by default) |
|
|
169
|
+
| `compare` | Two-host DNS + ping diff |
|
|
170
|
+
| `presets` | List available presets |
|
|
171
|
+
| `completion` | bash / zsh completions |
|
|
172
|
+
|
|
173
|
+
Also: `route`, `ifaces`, `local-ports`, `connections`, `whois`, `subnet`, `ip`, `ptr`, `mtr`, and more - `netdiag --help`.
|
|
174
|
+
|
|
175
|
+
All commands support `--json`.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Documentation
|
|
180
|
+
|
|
181
|
+
| Doc | Link |
|
|
182
|
+
|-----|------|
|
|
183
|
+
| Docs index | [docs/README.md](docs/README.md) |
|
|
184
|
+
| Cookbook (on-call recipes) | [docs/cookbook.md](docs/cookbook.md) |
|
|
185
|
+
| CLI contract (exit codes, flags) | [docs/CLI_CONTRACT.md](docs/CLI_CONTRACT.md) |
|
|
186
|
+
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) |
|
|
187
|
+
| Security | [SECURITY.md](SECURITY.md) |
|
|
188
|
+
| Roadmap | [ROADMAP.md](ROADMAP.md) |
|
|
189
|
+
| Changelog | [CHANGELOG.md](CHANGELOG.md) |
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Author
|
|
194
|
+
|
|
195
|
+
**Olúmáyòwá Akinkuehinmi** - [@akintunero](https://github.com/akintunero) · [akintunero101@gmail.com](mailto:akintunero101@gmail.com)
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT - see [LICENSE](LICENSE).
|
|
200
|
+
|
|
201
|
+
## Responsible use
|
|
202
|
+
|
|
203
|
+
Use only on networks and hosts you are authorized to test.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# netdiag
|
|
2
|
+
|
|
3
|
+
**Production runbook CLI for network incidents** - traceroute with ASN/BGP, DNS drift, latency, VPN checks, and on-call presets in one binary.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/akintunero/netdiag/actions/workflows/ci.yml)
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
**Stdlib-only at runtime** · **`--json` on every command** · **Exit codes built for automation**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
netdiag doctor
|
|
13
|
+
netdiag oncall <HOST> --json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
| Method | Command |
|
|
21
|
+
|--------|---------|
|
|
22
|
+
| From source (dev) | `python3 -m pip install -e ".[dev]"` |
|
|
23
|
+
| PyPI | `python3 -m pip install netdiag-cli` |
|
|
24
|
+
| From Git | `python3 -m pip install "git+https://github.com/akintunero/netdiag.git"` |
|
|
25
|
+
|
|
26
|
+
Use `python3 -m pip` (not bare `pip`) on macOS if `pip` is missing. The PyPI package is **`netdiag-cli`**; the command is still **`netdiag`**.
|
|
27
|
+
|
|
28
|
+
**System tools:** `ping` (required), plus `traceroute`, `dig`, and routing/socket tools as needed. Run `netdiag doctor` to see what is on your PATH.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Runbook workflow
|
|
33
|
+
|
|
34
|
+
| Step | Command | Exit code |
|
|
35
|
+
|------|---------|-----------|
|
|
36
|
+
| 1. Pre-flight | `netdiag doctor` | `0` ready · `2` missing required tools |
|
|
37
|
+
| 2. Incident check | `netdiag oncall <HOST> --json` | `0` pass · `1` fail · `2` error |
|
|
38
|
+
| 3. Ticket artifact | `netdiag report <HOST> -o incident.md` | same |
|
|
39
|
+
|
|
40
|
+
Exit code semantics are stable in v0.x - see [docs/CLI_CONTRACT.md](docs/CLI_CONTRACT.md).
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
netdiag oncall 1.1.1.1 --json
|
|
44
|
+
netdiag oncall YOUR-SERVICE.example.com --json | jq '.steps[] | select(.ok==false)'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> **Tip:** Run one command per line. Do not paste trailing `#` comments from docs into zsh/bash.
|
|
48
|
+
|
|
49
|
+
### VPN and corporate DNS
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
netdiag vpn --corp intranet.company.com
|
|
53
|
+
netdiag oncall app.internal --corp app.internal --vpn --json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Optional config
|
|
57
|
+
|
|
58
|
+
Copy [docs/config.example.toml](docs/config.example.toml) to `~/.config/netdiag/config.toml`:
|
|
59
|
+
|
|
60
|
+
```toml
|
|
61
|
+
[defaults]
|
|
62
|
+
corp_host = "app.internal.corp"
|
|
63
|
+
|
|
64
|
+
[oncall]
|
|
65
|
+
preset = "oncall"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Shell completions
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
eval "$(netdiag completion bash)"
|
|
72
|
+
eval "$(netdiag completion zsh)"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### About the CLI
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
netdiag --info # version, platform, repo links, wordmark banner
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Set `NETDIAG_NO_BANNER=1` to hide the banner.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Why operators use it
|
|
86
|
+
|
|
87
|
+
| | |
|
|
88
|
+
|---|---|
|
|
89
|
+
| **One CLI** | Replaces ad-hoc `dig` + `ping` + `curl` + `traceroute` scripts |
|
|
90
|
+
| **`--json`** | PagerDuty, CI, Slack bots, `jq` filters |
|
|
91
|
+
| **Presets** | `web`, `api`, `vpn`, `oncall` - tuned check bundles |
|
|
92
|
+
| **Small runtime** | No required PyPI dependencies |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Quick start (developers)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
git clone https://github.com/akintunero/netdiag.git
|
|
100
|
+
cd netdiag
|
|
101
|
+
python3 -m pip install -e ".[dev]"
|
|
102
|
+
netdiag doctor
|
|
103
|
+
python3 -m pytest tests/ -q
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Smoke test (live network, all subcommands):
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
bash scripts/cli_smoke.sh
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Example probes:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
netdiag oncall 1.1.1.1 --json
|
|
116
|
+
netdiag oncall 1.1.1.1 --preset api --json
|
|
117
|
+
netdiag trace 8.8.8.8 -m 12 --no-bgp-api
|
|
118
|
+
netdiag report 1.1.1.1 -o incident.md
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Command reference
|
|
124
|
+
|
|
125
|
+
| Command | Description |
|
|
126
|
+
|---------|-------------|
|
|
127
|
+
| **`doctor`** | Pre-flight: required tools for runbooks |
|
|
128
|
+
| **`oncall`** | Primary incident bundle (preset `oncall`) |
|
|
129
|
+
| `report` | Markdown report (`-o file.md`, `--vpn`) |
|
|
130
|
+
| `vpn` | VPN, split-tunnel, DNS drift |
|
|
131
|
+
| `check` | Health check; `--preset` for bundles |
|
|
132
|
+
| `trace` | Traceroute + ASN/BGP enrichment |
|
|
133
|
+
| `ping` / `latency` | RTT, jitter, percentiles |
|
|
134
|
+
| `dns` / `dns-trace` / `dns-compare` / `dns-all` | DNS tooling |
|
|
135
|
+
| `port` / `ports` | TCP probes and scans |
|
|
136
|
+
| `http` / `tls` / `redirects` / `headers` | Application layer |
|
|
137
|
+
| `speed` | CDN throughput (Cloudflare by default) |
|
|
138
|
+
| `compare` | Two-host DNS + ping diff |
|
|
139
|
+
| `presets` | List available presets |
|
|
140
|
+
| `completion` | bash / zsh completions |
|
|
141
|
+
|
|
142
|
+
Also: `route`, `ifaces`, `local-ports`, `connections`, `whois`, `subnet`, `ip`, `ptr`, `mtr`, and more - `netdiag --help`.
|
|
143
|
+
|
|
144
|
+
All commands support `--json`.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Documentation
|
|
149
|
+
|
|
150
|
+
| Doc | Link |
|
|
151
|
+
|-----|------|
|
|
152
|
+
| Docs index | [docs/README.md](docs/README.md) |
|
|
153
|
+
| Cookbook (on-call recipes) | [docs/cookbook.md](docs/cookbook.md) |
|
|
154
|
+
| CLI contract (exit codes, flags) | [docs/CLI_CONTRACT.md](docs/CLI_CONTRACT.md) |
|
|
155
|
+
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) |
|
|
156
|
+
| Security | [SECURITY.md](SECURITY.md) |
|
|
157
|
+
| Roadmap | [ROADMAP.md](ROADMAP.md) |
|
|
158
|
+
| Changelog | [CHANGELOG.md](CHANGELOG.md) |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Author
|
|
163
|
+
|
|
164
|
+
**Olúmáyòwá Akinkuehinmi** - [@akintunero](https://github.com/akintunero) · [akintunero101@gmail.com](mailto:akintunero101@gmail.com)
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT - see [LICENSE](LICENSE).
|
|
169
|
+
|
|
170
|
+
## Responsible use
|
|
171
|
+
|
|
172
|
+
Use only on networks and hosts you are authorized to test.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# CLI contract
|
|
2
|
+
|
|
3
|
+
Stable behavior for **production runbooks**, CI, and on-call automation.
|
|
4
|
+
Applies from **v0.1.0** onward unless a major version notes otherwise.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Exit codes
|
|
9
|
+
|
|
10
|
+
| Code | Name | Meaning | Typical action |
|
|
11
|
+
|------|------|---------|----------------|
|
|
12
|
+
| `0` | `EX_OK` | Ran successfully; checks passed | Close alert / continue |
|
|
13
|
+
| `1` | `EX_FAIL` | Ran successfully; target or check failed | Page, escalate, retry |
|
|
14
|
+
| `2` | `EX_ERROR` | Cannot run reliably (config, missing tool, bad args) | Fix host, install tools, fix script |
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
netdiag oncall 1.1.1.1 --json
|
|
18
|
+
echo $? # 0 = pass, 1 = fail, 2 = error
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Stability (v0.x):** These three meanings will not change. New failure modes map to `1` or `2`.
|
|
22
|
+
|
|
23
|
+
### Examples
|
|
24
|
+
|
|
25
|
+
| Situation | Code |
|
|
26
|
+
|-----------|------|
|
|
27
|
+
| `oncall` - all steps pass | `0` |
|
|
28
|
+
| `oncall` - ping loss or TLS expiring soon | `1` |
|
|
29
|
+
| `dns` - `dig` not installed | `2` |
|
|
30
|
+
| `doctor` - required `ping` missing | `2` |
|
|
31
|
+
| Invalid CLI arguments | `2` |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Primary workflow
|
|
36
|
+
|
|
37
|
+
Memorize one command:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
netdiag oncall <HOST> --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
With corporate DNS context:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
netdiag oncall <HOST> --json --corp app.internal
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Markdown artifact for tickets:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
netdiag report <HOST> -o incident.md --vpn --corp app.internal
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Pre-flight before runbooks:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
netdiag doctor # exit 0 = ready, 2 = missing required tools
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Stable flags (v0.x)
|
|
64
|
+
|
|
65
|
+
| Flag | Commands | Notes |
|
|
66
|
+
|------|----------|-------|
|
|
67
|
+
| `--json` | All subcommands | Schema may grow; existing keys stay |
|
|
68
|
+
| `--preset {web,api,vpn,oncall}` | `check`, `oncall`, `report` | Check bundle selection |
|
|
69
|
+
| `--corp HOST` | `check`, `oncall`, `report`, `vpn` | Corporate resolver context |
|
|
70
|
+
| `--no-bgp-api` | `trace`, `whois` | Skip external BGP HTTP APIs |
|
|
71
|
+
| `--vpn` | `oncall`, `report`, `vpn` | Include VPN-related checks |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## JSON output
|
|
76
|
+
|
|
77
|
+
- One JSON object per invocation when `--json` is set (some commands embed arrays under a key).
|
|
78
|
+
- Failures may include an `"error"` field with a human-readable message.
|
|
79
|
+
- Intended for `jq` in runbooks, e.g.:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
netdiag oncall "$HOST" --json | jq '.steps[] | select(.ok == false)'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Optional config
|
|
88
|
+
|
|
89
|
+
Path: `~/.config/netdiag/config.toml`
|
|
90
|
+
Example: [config.example.toml](config.example.toml)
|
|
91
|
+
|
|
92
|
+
Config changes defaults only; it does **not** change exit code semantics.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Versioning policy
|
|
97
|
+
|
|
98
|
+
| Series | Policy |
|
|
99
|
+
|--------|--------|
|
|
100
|
+
| **v0.x** | Additive only - new commands, JSON keys, optional flags |
|
|
101
|
+
| **v1.0+** | Breaking exit-code or flag removals only with major version + CHANGELOG migration notes |
|
|
102
|
+
|
|
103
|
+
See [CHANGELOG.md](../CHANGELOG.md) for release history.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
Guides and reference for **netdiag** - a stdlib-only CLI for SRE and on-call network troubleshooting.
|
|
4
|
+
|
|
5
|
+
| Document | Purpose |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| [Cookbook](cookbook.md) | On-call recipes: DNS, API outage, VPN, TLS, automation |
|
|
8
|
+
| [CLI contract](CLI_CONTRACT.md) | Exit codes `0` / `1` / `2`, stable flags, JSON conventions |
|
|
9
|
+
| [Config example](config.example.toml) | Optional `~/.config/netdiag/config.toml` |
|
|
10
|
+
|
|
11
|
+
## Runbook essentials
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
netdiag doctor
|
|
15
|
+
netdiag oncall <HOST> --json
|
|
16
|
+
netdiag report <HOST> -o incident.md
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Use a real hostname or IP (`1.1.1.1`, your service FQDN). Names like `api.example.com` are reserved ([RFC 6761](https://datatracker.ietf.org/doc/html/rfc6761)) and will not resolve on the public internet.
|
|
20
|
+
|
|
21
|
+
## Project docs (repo root)
|
|
22
|
+
|
|
23
|
+
| Document | Purpose |
|
|
24
|
+
|----------|---------|
|
|
25
|
+
| [README](../README.md) | Install, command overview, quick start |
|
|
26
|
+
| [CONTRIBUTING](../CONTRIBUTING.md) | Development setup and PR expectations |
|
|
27
|
+
| [SECURITY](../SECURITY.md) | Vulnerability reporting |
|
|
28
|
+
| [ROADMAP](../ROADMAP.md) | Planned work and non-goals |
|
|
29
|
+
| [CHANGELOG](../CHANGELOG.md) | Release history |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# netdiag configuration
|
|
2
|
+
# Copy to: ~/.config/netdiag/config.toml
|
|
3
|
+
#
|
|
4
|
+
# All keys are optional. CLI flags override these defaults.
|
|
5
|
+
|
|
6
|
+
[defaults]
|
|
7
|
+
# Corporate hostname for resolver compare and VPN checks
|
|
8
|
+
# corp_host = "app.internal.corp"
|
|
9
|
+
|
|
10
|
+
# Skip BGP/ASN HTTP enrichment globally where supported
|
|
11
|
+
# no_bgp_api = false
|
|
12
|
+
|
|
13
|
+
# Default JSON output for commands that support --json
|
|
14
|
+
# json = false
|
|
15
|
+
|
|
16
|
+
[oncall]
|
|
17
|
+
# Preset for `netdiag oncall` / `report` when --preset is omitted
|
|
18
|
+
preset = "oncall"
|
|
19
|
+
|
|
20
|
+
# Override corp host for on-call runs only
|
|
21
|
+
# corp_host = "app.internal.corp"
|