termainer 0.4.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.
Files changed (42) hide show
  1. termainer-0.4.0/PKG-INFO +419 -0
  2. termainer-0.4.0/README.md +397 -0
  3. termainer-0.4.0/pyproject.toml +55 -0
  4. termainer-0.4.0/setup.cfg +4 -0
  5. termainer-0.4.0/src/termainer/__init__.py +0 -0
  6. termainer-0.4.0/src/termainer/app.py +242 -0
  7. termainer-0.4.0/src/termainer/config.py +82 -0
  8. termainer-0.4.0/src/termainer/config_manager.py +75 -0
  9. termainer-0.4.0/src/termainer/locale.py +460 -0
  10. termainer-0.4.0/src/termainer/providers/__init__.py +0 -0
  11. termainer-0.4.0/src/termainer/providers/base.py +61 -0
  12. termainer-0.4.0/src/termainer/providers/docker.py +213 -0
  13. termainer-0.4.0/src/termainer/providers/kubernetes.py +239 -0
  14. termainer-0.4.0/src/termainer/providers/openshift.py +77 -0
  15. termainer-0.4.0/src/termainer/providers/podman.py +158 -0
  16. termainer-0.4.0/src/termainer/providers/swarm.py +211 -0
  17. termainer-0.4.0/src/termainer/remote/__init__.py +0 -0
  18. termainer-0.4.0/src/termainer/remote/ssh.py +157 -0
  19. termainer-0.4.0/src/termainer/server_manager.py +84 -0
  20. termainer-0.4.0/src/termainer/ssh_config.py +138 -0
  21. termainer-0.4.0/src/termainer/ui/__init__.py +0 -0
  22. termainer-0.4.0/src/termainer/ui/dashboard.py +837 -0
  23. termainer-0.4.0/src/termainer/ui/environment.py +300 -0
  24. termainer-0.4.0/src/termainer/ui/home.py +263 -0
  25. termainer-0.4.0/src/termainer/ui/splash.py +89 -0
  26. termainer-0.4.0/src/termainer/ui/widgets.py +335 -0
  27. termainer-0.4.0/src/termainer/utils/__init__.py +0 -0
  28. termainer-0.4.0/src/termainer/utils/helpers.py +56 -0
  29. termainer-0.4.0/src/termainer/version.py +1 -0
  30. termainer-0.4.0/src/termainer.egg-info/PKG-INFO +419 -0
  31. termainer-0.4.0/src/termainer.egg-info/SOURCES.txt +40 -0
  32. termainer-0.4.0/src/termainer.egg-info/dependency_links.txt +1 -0
  33. termainer-0.4.0/src/termainer.egg-info/entry_points.txt +2 -0
  34. termainer-0.4.0/src/termainer.egg-info/requires.txt +6 -0
  35. termainer-0.4.0/src/termainer.egg-info/top_level.txt +1 -0
  36. termainer-0.4.0/tests/test_app.py +44 -0
  37. termainer-0.4.0/tests/test_config.py +136 -0
  38. termainer-0.4.0/tests/test_config_manager.py +205 -0
  39. termainer-0.4.0/tests/test_providers.py +358 -0
  40. termainer-0.4.0/tests/test_server_manager.py +213 -0
  41. termainer-0.4.0/tests/test_ssh_config.py +145 -0
  42. termainer-0.4.0/tests/test_ui.py +101 -0
@@ -0,0 +1,419 @@
1
+ Metadata-Version: 2.4
2
+ Name: termainer
3
+ Version: 0.4.0
4
+ Summary: Container observability and operations directly from your terminal
5
+ Author: Alan Stefanov
6
+ License: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: System :: Monitoring
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: textual>=1.0.0
18
+ Requires-Dist: rich>=13.0.0
19
+ Requires-Dist: pyyaml>=6.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: python-semantic-release>=9.0; extra == "dev"
22
+
23
+ <div align="center">
24
+
25
+ # Alan Stefanov
26
+
27
+ ### Engineering Manager · Developer Experience · Platform Engineering · FinOps · Cloud Architecture
28
+
29
+ Building scalable platforms, leading teams, and optimizing cloud operations.
30
+
31
+ [![LinkedIn](https://img.shields.io/badge/LinkedIn-Alan_Stefanov-blue?style=for-the-badge&logo=linkedin)](https://www.linkedin.com/in/alanstefanov/)
32
+ [![Email](https://img.shields.io/badge/Email-alan.emanuel.stefanov@gmail.com-red?style=for-the-badge&logo=gmail)](mailto:alan.emanuel.stefanov@gmail.com)
33
+ [![GitHub](https://img.shields.io/badge/GitHub-AlanStefanov-black?style=for-the-badge&logo=github)](https://github.com/AlanStefanov)
34
+
35
+ </div>
36
+
37
+ ---
38
+
39
+ <p align="center">
40
+ <img src="https://i.ibb.co/BKK1DspJ/Black-Minimal-Motivation-Quote-Linked-In-Banner-1.png" alt="Alan Stefanov Banner"/>
41
+ </p>
42
+
43
+ ---
44
+
45
+ <div align="center">
46
+
47
+ # Termainer
48
+
49
+ **Container observability and operations directly from your terminal.**
50
+
51
+ <p align="center">
52
+ <img src="src/termainer/ui/logo.png" alt="Termainer Logo" width="600"/>
53
+ </p>
54
+
55
+ [![GitHub](https://img.shields.io/badge/GitHub-AlanStefanov/termainer-181717?style=flat-square&logo=github)](https://github.com/AlanStefanov/termainer)
56
+ [![Python](https://img.shields.io/badge/Python-3.10+-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
57
+ [![License](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)](LICENSE)
58
+ [![PyPI](https://img.shields.io/badge/PyPI-0.1.0-blue?style=flat-square&logo=pypi&logoColor=white)](https://pypi.org/project/termainer/)
59
+ [![Docker Hub](https://img.shields.io/badge/Docker%20Hub-alanstefanov%2Ftermainer-2496ED?style=flat-square&logo=docker)](https://hub.docker.com/r/alanstefanov/termainer)
60
+ [![Homebrew](https://img.shields.io/badge/Homebrew-coming%20soon-FBB040?style=flat-square&logo=homebrew)](https://github.com/AlanStefanov/homebrew-termainer)
61
+ [![Textual](https://img.shields.io/badge/Built%20with-Textual-6C5CE7?style=flat-square)](https://textual.textualize.io/)
62
+ [![LinkedIn](https://img.shields.io/badge/LinkedIn-Alan%20Stefanov-0A66C2?style=flat-square&logo=linkedin)](https://www.linkedin.com/in/alanstefanov/)
63
+
64
+ <br>
65
+
66
+ > Everything you need to know about all your containers, in a single terminal.
67
+
68
+ </div>
69
+
70
+ ---
71
+
72
+ ## Features
73
+
74
+ | | |
75
+ |---|---|
76
+ | **📊 Live Stats** | Real-time CPU, memory, and network I/O with sparkline charts |
77
+ | **📜 Log Streaming** | Live logs with pause/resume, scroll support, and syntax highlighting |
78
+ | **🔍 Full Inspection** | Environment variables, networks, volumes, ports, and configuration |
79
+ | **🔌 Multi-Provider** | Supports **Docker**, **Docker Swarm**, **Podman**, **Kubernetes**, and **OpenShift** |
80
+ | **📤 Report Export** | Save logs with metadata for debugging and bug reporting |
81
+ | **🌐 Remote SSH Connection** | Connect to remote servers (EC2, VPS, etc.) running Docker or K8s |
82
+ | **🖥️ Multi-Server** | Monitor multiple remote and local servers simultaneously |
83
+ | **⚡ Modern TUI** | Built with Textual and Rich — fast, responsive, and terminal-native |
84
+ | **🔄 Container Lifecycle** | Start, stop, restart, and remove containers (Docker/Podman) |
85
+
86
+ ---
87
+
88
+ ## Installation
89
+
90
+ ### From PyPI (recommended)
91
+
92
+ ```bash
93
+ pip install termainer
94
+ ```
95
+
96
+ ### From Docker (ghcr.io — recommended)
97
+
98
+ ```bash
99
+ docker run -it -v /var/run/docker.sock:/var/run/docker.sock \
100
+ ghcr.io/alanstefanov/termainer:latest
101
+ ```
102
+
103
+ ### From Docker Hub (optional)
104
+
105
+ ```bash
106
+ docker run -it -v /var/run/docker.sock:/var/run/docker.sock \
107
+ alanstefanov/termainer:latest
108
+ ```
109
+
110
+ ### From source with install.sh
111
+
112
+ ```bash
113
+ git clone https://github.com/AlanStefanov/termainer.git
114
+ cd termainer
115
+ chmod +x install.sh
116
+ ./install.sh
117
+ ```
118
+
119
+ Make sure `~/.local/bin` is in your `PATH`:
120
+
121
+ ```bash
122
+ export PATH="$PATH:$HOME/.local/bin"
123
+ termainer
124
+ ```
125
+
126
+ ### Manual
127
+
128
+ ```bash
129
+ git clone https://github.com/AlanStefanov/termainer.git
130
+ cd termainer
131
+ python -m venv venv
132
+ source venv/bin/activate
133
+ pip install -r requirements.txt
134
+ pip install -e .
135
+ termainer
136
+ ```
137
+
138
+ ### Homebrew (coming soon)
139
+
140
+ ```bash
141
+ # Once available in the official tap:
142
+ brew install termainer
143
+ ```
144
+
145
+ In the meantime you can install manually from the [community tap](https://github.com/AlanStefanov/homebrew-termainer).
146
+
147
+ ---
148
+
149
+ ## Updating
150
+
151
+ Depending on how you installed Termainer:
152
+
153
+ | Method | Command |
154
+ |--------|---------|
155
+ | **pip** | `pip install --upgrade termainer` |
156
+ | **Docker (ghcr.io)** | `docker pull ghcr.io/alanstefanov/termainer:latest` |
157
+ | **Docker Hub** | `docker pull alanstefanov/termainer:latest` |
158
+ | **install.sh** | `cd termainer && git pull && ./install.sh` |
159
+
160
+ ---
161
+
162
+ ## Configuration
163
+
164
+ Termainer uses a **YAML config file** to manage multiple servers. Create `~/.config/termainer/config.yaml`:
165
+
166
+ ```yaml
167
+ lang: en
168
+
169
+ servers:
170
+ - label: "Local Docker"
171
+ provider: docker
172
+ # No host needed for local Docker
173
+
174
+ - label: "Production Web"
175
+ host: ec2-54-123-45-67.us-east-1.compute.amazonaws.com
176
+ user: ubuntu
177
+ key: ~/.ssh/production.pem
178
+ provider: docker
179
+
180
+ - label: "Staging K8s"
181
+ host: k8s-staging.example.com
182
+ user: admin
183
+ key: ~/.ssh/staging-key
184
+ provider: kubernetes
185
+ ```
186
+
187
+ See the full [Configuration Reference](guide/configuration-reference.md) for all options.
188
+
189
+ ### Quick single-server (.env)
190
+
191
+ For a single remote server, you can use `.env` or CLI flags instead:
192
+
193
+ ```bash
194
+ termainer --host ec2-54-123-45-67.us-east-1.compute.amazonaws.com \
195
+ --ssh-user ubuntu \
196
+ --ssh-key ~/.ssh/production.pem \
197
+ --provider docker
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Usage
203
+
204
+ ### Display Tips (Low Resolution)
205
+
206
+ If your terminal has low vertical space (for example 1366x768), reduce terminal zoom one or two steps before launching Termainer. In most terminals this is Control + Minus.
207
+
208
+ Termainer also has responsive modes, but zooming out slightly improves readability and avoids panel clipping.
209
+
210
+ ### Local
211
+
212
+ ```bash
213
+ # Auto-detect provider
214
+ termainer
215
+
216
+ # Specific provider
217
+ termainer --provider docker
218
+ termainer --provider swarm
219
+ termainer --provider podman
220
+ termainer --provider kubernetes
221
+ termainer --provider openshift
222
+ ```
223
+
224
+ ### Remote (SSH)
225
+
226
+ Connect to remote servers running Docker or Kubernetes:
227
+
228
+ ```bash
229
+ # Using CLI flags
230
+ termainer --host ec2-54-123-45-67.us-east-1.compute.amazonaws.com \
231
+ --ssh-user ubuntu \
232
+ --ssh-key ~/.ssh/production.pem \
233
+ --provider docker
234
+
235
+ # Using .env (recommended for frequent use)
236
+ cp .env.example .env
237
+ # Edit .env with your server details
238
+ termainer
239
+ ```
240
+
241
+ #### SSH Config Auto-Discovery (Recommended)
242
+
243
+ Termainer automatically discovers servers from your **`~/.ssh/config`** file. This is the **recommended approach** for multi-server setups—no `.env` file needed!
244
+
245
+ Simply define your remote servers in `~/.ssh/config`:
246
+
247
+ ```
248
+ Host prod-web
249
+ HostName ec2-54-123-45-67.us-east-1.compute.amazonaws.com
250
+ User ubuntu
251
+ IdentityFile ~/.ssh/production.pem
252
+
253
+ Host staging-k8s
254
+ HostName k8s-staging.example.com
255
+ User admin
256
+ IdentityFile ~/.ssh/staging-key
257
+
258
+ Host dev-local
259
+ HostName 192.168.1.100
260
+ User devuser
261
+ IdentityFile ~/.ssh/dev-key
262
+ ```
263
+
264
+ Then launch Termainer:
265
+
266
+ ```bash
267
+ termainer
268
+ ```
269
+
270
+ You'll see all servers from your SSH config automatically loaded in the server dropdown. No configuration files needed!
271
+
272
+ > **⚠️ Important:** Remote servers must have the Docker CLI installed and the Docker
273
+ > daemon socket accessible **without `sudo`**. The user connecting via SSH must be
274
+ > a member of the `docker` group (or equivalent) so that `docker ps`, `docker inspect`,
275
+ > etc. work without privilege escalation. Termainer uses SSH port forwarding to
276
+ > tunnel the remote Docker socket to a local Unix socket, so all Docker commands
277
+ > run locally against the forwarded socket — this avoids issues with remote Docker
278
+ > versions, PATH, and `--format` compatibility.
279
+
280
+ #### SSH Authentication Methods
281
+
282
+ | Method | How to use |
283
+ |---|---|
284
+ | **Key (`.pem`)** | `--ssh-key ~/.ssh/key.pem` or `TERMAINER_REMOTE_KEY_PATH` in `.env` |
285
+ | **Password** | `--ssh-password 'mypass'` or `TERMAINER_REMOTE_PASSWORD` in `.env` (requires `sshpass`) |
286
+
287
+ For password-based auth, install `sshpass`:
288
+
289
+ ```bash
290
+ # Debian/Ubuntu
291
+ sudo apt install sshpass
292
+
293
+ # RHEL/CentOS/Fedora
294
+ sudo yum install sshpass
295
+ ```
296
+
297
+ ### Multi-Server Dashboard
298
+
299
+ The environment screen is technology-first (`Docker`, `Swarm`, `Kubernetes`, `Podman`, `OpenShift`).
300
+
301
+ When you configure multiple servers (via `config.yaml` or `~/.ssh/config`), each technology dashboard can aggregate its related servers. You can:
302
+
303
+ - **Server dropdown** at the top of the dashboard to select a specific server
304
+ - **"Todos" (All)** option to see resources from all servers for that technology
305
+ - **Switch servers anytime** using the server dropdown in the sidebar
306
+ - Each container shows its **server name** prefix when in multi-server mode
307
+
308
+ The sidebar dropdown automatically populates with:
309
+ - **Local** (your machine)
310
+ - SSH servers from `~/.ssh/config`
311
+ - Servers from `config.yaml` (if configured)
312
+
313
+ ### Keyboard Shortcuts
314
+
315
+ #### Technology selection screen
316
+
317
+ | Key | Action |
318
+ |---|---|
319
+ | `←` / `↑` / `↓` / `→` | Navigate technologies |
320
+ | `Enter` | Open technology dashboard |
321
+ | `q` | Quit |
322
+
323
+ #### Container dashboard
324
+
325
+ | Key | Action |
326
+ |---|---|---|
327
+ | `↑` / `↓` | Navigate container list |
328
+ | `Enter` | Select container |
329
+ | `F5` | Refresh list |
330
+ | `p` | Pause/resume logs |
331
+ | `e` | Export logs |
332
+ | `a` | Start container |
333
+ | `t` | Stop container |
334
+ | `r` | Restart container |
335
+ | `o` | Restart policy |
336
+ | `c` | Exec command |
337
+ | `Delete` | Remove container |
338
+ | `Escape` | Back to technology selection |
339
+ | `q` | Quit |
340
+
341
+ ---
342
+
343
+ ## Supported Providers
344
+
345
+ | Provider | List | Inspect | Stats | Logs | Env Vars | Start/Stop/Restart | Remove |
346
+ |---|---|---|---|---|---|---|---|---|
347
+ |---|---|---|---|---|---|---|---|
348
+ | **Docker** | ✅ | ✅ | ✅ (stream) | ✅ (follow) | ✅ | ✅ | ✅ |
349
+ | **Docker Swarm** | ✅ (services) | ✅ | ⚠️ basic | ✅ (service logs) | ✅ | ✅ (scale/update) | ✅ |
350
+ | **Podman** | ✅ | ✅ | ✅ (poll) | ✅ (follow) | ✅ | ✅ | ✅ |
351
+ | **Kubernetes** | ✅ | ✅ | ✅ (top) | ✅ (follow) | ✅ | ❌ | ✅ |
352
+ | **OpenShift** | ✅ | ✅ | ✅ (top) | ✅ (follow) | ✅ | ❌ | ✅ |
353
+
354
+ All providers work both locally and remotely via SSH.
355
+
356
+ ---
357
+
358
+ ## Architecture
359
+
360
+ ```
361
+ CLI (termainer)
362
+ └── app.py ← CLI args, .env loading, SSH conn
363
+ ├── config_manager.py ← YAML config parser (multi-server)
364
+ ├── server_manager.py ← Multi-server connection manager
365
+ ├── remote/ ← Remote connection module
366
+ │ └── ssh.py ← SSH via subprocess (key + password)
367
+ ├── config.py ← .env parser and SSH builder
368
+ ├── providers/ ← Multi-provider abstraction layer
369
+ │ ├── base.py ← Abstract Protocol
370
+ │ ├── docker.py ← Docker CLI (local + remote)
371
+ │ ├── swarm.py ← Docker Swarm services (local + remote)
372
+ │ ├── podman.py ← Podman CLI (local + remote)
373
+ │ ├── kubernetes.py ← kubectl (local + remote)
374
+ │ └── openshift.py ← oc (extends K8s)
375
+ ├── ui/ ← TUI layer (Textual)
376
+ │ ├── splash.py ← Welcome screen
377
+ │ ├── dashboard.py ← Main dashboard
378
+ │ ├── widgets.py ← Reusable widgets
379
+ │ └── styles.tcss ← Stylesheet
380
+ └── utils/
381
+ └── helpers.py ← Utilities
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Tech Stack
387
+
388
+ | Component | Technology |
389
+ |---|---|
390
+ | Language | Python 3.10+ |
391
+ | UI Framework | [Textual](https://textual.textualize.io/) |
392
+ | Rendering | [Rich](https://rich.readthedocs.io/) |
393
+ | Configuration | YAML (via PyYAML) |
394
+ | Providers | Docker CLI, Docker Swarm, Podman CLI, kubectl, oc |
395
+ | Remote Access | SSH via subprocess (key + sshpass) |
396
+ | Async | asyncio |
397
+ | Testing | pytest, pytest-asyncio |
398
+ | Linting | Ruff |
399
+
400
+ ---
401
+
402
+ ## Documentation
403
+
404
+ - [Configuration Reference](guide/configuration-reference.md)
405
+ - [Configuration Reference (ES)](guide/configuration-reference-es.md)
406
+
407
+ ---
408
+
409
+ ## License
410
+
411
+ MIT — [Alan Emanuel Stefanov](https://github.com/AlanStefanov)
412
+
413
+ ---
414
+
415
+ <p align="center">
416
+ ⭐ If you like this project, give it a star on GitHub — it helps others discover it!
417
+ <br>
418
+ <a href="https://github.com/AlanStefanov/termainer">github.com/AlanStefanov/termainer</a>
419
+ </p>