Commit Graph

134 Commits

Author SHA1 Message Date
Bas Nijholt
ca46fdfaa4 Replace trivial examples with real-world services
- traefik: Reverse proxy with Let's Encrypt DNS challenge
- mealie: Single container with resource limits
- uptime-kuma: Monitoring with Docker socket and user mapping
- paperless-ngx: Multi-container stack (Redis + SQLite)
- autokuma: Multi-host service (runs on all hosts)

Each example demonstrates dual Traefik routes:
- HTTPS (websecure): Custom domain with Let's Encrypt TLS
- HTTP (web): .local domain for LAN access without TLS

Includes compose-farm.yaml with multi-host config and
compose-farm-state.yaml showing deployed state.
2025-12-15 14:08:14 -08:00
Bas Nijholt
b480797e5b Add XDG_CONFIG_HOME support for config paths
Respect the XDG_CONFIG_HOME environment variable when looking for
config files and log paths. Falls back to ~/.config if not set.
2025-12-15 13:06:59 -08:00
Bas Nijholt
c47fdf847e Use _progress_bar helper for all progress bars
Standardize UI by using the same progress bar configuration
everywhere. Removes unused TaskProgressColumn import.
2025-12-15 13:03:50 -08:00
Bas Nijholt
3ca9562013 Consolidate console instances and progress bar patterns
- Add console.py module with shared Console instances
- Add _progress_bar() helper to reduce progress bar boilerplate
- Update cli.py, executor.py, operations.py to use shared console
2025-12-15 12:56:23 -08:00
Bas Nijholt
3104d5de28 Refactor state.py with context manager and cli.py with helper to reduce duplication 2025-12-15 11:10:44 -08:00
Bas Nijholt
fd141cbc8c Refactor executor and operations to eliminate code duplication 2025-12-15 11:07:58 -08:00
Bas Nijholt
aa0c15b6b3 Add project metadata to pyproject.toml
Add license, maintainers, keywords, classifiers, and project URLs
for better discoverability on PyPI.
2025-12-15 11:07:13 -08:00
Bas Nijholt
4630a3e551 Merge pull request #4 from basnijholt/feature/multi-host-services
Add multi-host service support
2025-12-15 10:58:36 -08:00
Bas Nijholt
b70d5c52f1 fix: Use strict=True in zip() for equal-length lists 2025-12-15 10:56:47 -08:00
Bas Nijholt
5d8635ba7b ci: Use prek in CI instead of separate ruff/mypy commands
prek is a faster, Rust-based alternative to pre-commit.
Also updates ruff-pre-commit to v0.14.9 to match project version.
2025-12-15 10:53:34 -08:00
Bas Nijholt
27dad9d9d5 style: Format cli.py 2025-12-15 10:51:51 -08:00
Bas Nijholt
abb4417b15 Add orphaned service detection in check command
Warns when services are in state but not in config. These are
services that were removed from config but may still be running.
Also refactors remote checks into helper function.
2025-12-15 10:43:10 -08:00
Bas Nijholt
388cca5591 Add summary output showing succeeded/failed service counts 2025-12-15 10:38:36 -08:00
Bas Nijholt
8aa019e25f fix: Move imports to top-level in test file 2025-12-15 10:29:29 -08:00
Bas Nijholt
e4061cfbde Fix down command for multi-host services
The result.service for multi-host services is 'svc@host' format.
Extract base service name before removing from state.
2025-12-15 10:09:15 -08:00
Bas Nijholt
9a1f20e2d4 Add per-host control and partial state tracking
- Track partial success: if some hosts succeed, state reflects
  only the hosts that actually started
- Add --host flag to up/down: operate on a specific host only
  - `cf up autokuma --host nuc` starts only on nuc
  - `cf down autokuma --host nuc` stops only on nuc
- Add state helpers: add_service_to_host, remove_service_from_host
- Validate --host is allowed for the service's configured hosts
2025-12-15 09:51:49 -08:00
Bas Nijholt
3b45736729 Validate multi-host config edge cases
- Block 'all' as a host name (reserved keyword)
- Reject empty host lists
- Reject duplicate hosts in explicit lists
2025-12-15 09:46:29 -08:00
Bas Nijholt
1d88fa450a docs: Explain why multi-host services are needed 2025-12-15 09:37:41 -08:00
Bas Nijholt
31ee6be163 Add multi-host service support
Allows services to run on multiple hosts using the "all" keyword
or an explicit list of hosts:

  services:
    autokuma: all              # Run on all configured hosts
    dozzle: [host1, host2]     # Run on specific hosts

Key changes:
- config.py: Added get_hosts() and is_multi_host() methods
- executor.py: Added run_compose_multi_host() for parallel execution
- operations.py: Added _up_multi_host_service() with pre-flight checks
- state.py: Track list of hosts for multi-host services
- cli.py: Updated discovery, stats, and check for multi-host
- README.md: Added documentation

Multi-host services:
- Run on all target hosts in parallel
- Skip migration logic (always run everywhere)
- Show [service@host] prefix in output
- Track all running hosts in state
2025-12-15 09:14:25 -08:00
Bas Nijholt
096a2ca5f4 sync: Remove extra spacing (transient bar already leaves one) 2025-12-14 20:41:38 -08:00
Bas Nijholt
fb04f6f64d sync: Add spacing before capturing progress bar 2025-12-14 20:39:02 -08:00
Bas Nijholt
d8e54aa347 check: Fix double newline spacing in output v0.13.0 2025-12-14 20:35:25 -08:00
Bas Nijholt
b2b6b421ba check: Add spacing before mounts/networks progress bar 2025-12-14 20:33:36 -08:00
Bas Nijholt
c6b35f02f0 check: Add spacing before SSH progress bar 2025-12-14 20:32:16 -08:00
Bas Nijholt
7e43b0a6b8 check: Fix spacing after transient progress bar 2025-12-14 20:31:20 -08:00
Bas Nijholt
2915b287ba check: Add SSH connectivity check as first remote step
- Check SSH connectivity to all remote hosts before mount/network checks
- Skip local hosts (no SSH needed)
- Show progress bar during SSH checks
- Report unreachable hosts with clear error messages
- Add newline spacing for better output formatting
2025-12-14 20:30:36 -08:00
Bas Nijholt
ae561db0c9 check: Add progress bar and parallelize mount/network checks
- Parallelize mount and network checking for all services
- Add Rich progress bar showing count, elapsed time, and service name
- Move all inline imports to top-level (contextlib, datetime, logs)
- Also sort state file entries alphabetically for consistency
2025-12-14 20:24:54 -08:00
Bas Nijholt
2d132747c4 sync: Enhance progress bars with count and elapsed time
Show "Discovering ━━━━ 32/65 • 0:00:05 • service-name" format with:
- M of N complete count
- Elapsed time
- Current service name
2025-12-14 20:15:39 -08:00
Bas Nijholt
2848163a04 sync: Add progress bars and parallelize operations
- Parallelize service discovery across all services
- Parallelize image digest capture
- Show transient Rich progress bars during both operations
- Significantly faster sync due to concurrent SSH connections
2025-12-14 20:13:42 -08:00
Bas Nijholt
76aa6e11d2 logs: Make --all and --host mutually exclusive
These options conflict conceptually - --all means all services across
all hosts, while --host means all services on a specific host.
2025-12-14 20:10:28 -08:00
Bas Nijholt
d377df15b4 logs: Add --host filter and contextual --tail default
- Add --host/-H option to filter logs to services on a specific host
- Default --tail to 20 lines when showing multiple services (--all, --host, or >1 service)
- Default to 100 lines for single service
- Add tests for contextual default and host filtering
2025-12-14 20:04:40 -08:00
Bas Nijholt
334c17cc28 logs: Use contextual default for --tail option
Default to 20 lines when --all is specified (quick overview),
100 lines otherwise (detailed view for specific services).
2025-12-14 19:59:12 -08:00
Bas Nijholt
f148b5bd3a docs: Add TrueNAS NFS root squash configuration guide
Explains how to set maproot_user/maproot_group to root/wheel
in TrueNAS to disable root squash, allowing Docker containers
running as root to write to NFS-mounted volumes.
v0.12.0
2025-12-14 17:24:46 -08:00
Bas Nijholt
54af649d76 Make stats progress bar transient v0.11.0 2025-12-14 15:31:00 -08:00
Bas Nijholt
f6e5a5fa56 Add progress bar when querying hosts in stats --live 2025-12-14 15:30:37 -08:00
Bas Nijholt
01aa24d0db style: Add borders to stats summary table 2025-12-14 15:25:17 -08:00
Bas Nijholt
3e702ef72e Add stats command for overview of hosts and services
Shows hosts table (address, configured/running services) and summary
(total hosts, services, compose files on disk, pending migrations).
Use --live to query Docker for actual container counts.
2025-12-14 15:24:30 -08:00
Bas Nijholt
a31218f7e5 docs: Remove trivial progress counter detail 2025-12-14 15:16:45 -08:00
Bas Nijholt
5decb3ed95 docs: Add --migrate flag and hybrid SSH approach 2025-12-14 15:14:56 -08:00
Bas Nijholt
da61436fbb Use native ssh for raw mode, asyncssh for streaming
- Raw mode uses subprocess with `ssh -t` for proper TTY handling
- Progress bars now render correctly on remote hosts
- asyncssh still used for non-raw parallel streaming with prefixes
- Remove redundant header prints (operations.py handles them)
v0.10.0
2025-12-14 15:12:48 -08:00
Bas Nijholt
b6025af0c8 Fix newline after raw output to prevent line mixing 2025-12-14 14:49:33 -08:00
Bas Nijholt
ab914677c4 Add progress counter [n/total] to up command 2025-12-14 14:48:48 -08:00
Bas Nijholt
c0b421f812 Add --migrate flag to up command
Automatically detects services where state differs from config
and migrates only those. Usage: cf up --migrate or cf up -m
2025-12-14 14:47:43 -08:00
Bas Nijholt
2a446c800f Always use raw output for up command
- Print service header before raw output (local and SSH)
- up command always uses raw=True since migrations are sequential
- Gives clean progress bar output without per-line prefixes
2025-12-14 14:44:53 -08:00
Bas Nijholt
dc541c0298 test: Skip shell-dependent tests on Windows/Mac 2025-12-14 14:28:31 -08:00
Bas Nijholt
4d9b8b5ba4 docs: Add TrueNAS NFS crossmnt workaround
Documents how to access child ZFS datasets over NFS by injecting
the crossmnt option into /etc/exports. Includes Python script and
setup instructions for cron-based persistence.
2025-12-14 14:11:10 -08:00
Bas Nijholt
566a07d3a4 Refactor: separate concerns into dedicated modules
- Extract compose.py from traefik.py for generic compose parsing
  (env loading, interpolation, ports, volumes, networks)
- Rename ssh.py to executor.py for clarity
- Extract operations.py from cli.py for business logic
  (up_services, discover_running_services, preflight checks)
- Update CLAUDE.md with new architecture diagram
- Add docs/dev/future-improvements.md for low-priority items

CLI is now a thin layer that delegates to operations module.
All 70 tests pass.
2025-12-14 12:49:24 -08:00
Bas Nijholt
921ce6f13a Add raw output mode for single-service operations
When operating on a single service, pass output directly to
stdout/stderr instead of prefixing each line with [service].
This enables proper handling of \r progress bars during
docker pull, up, etc.
2025-12-14 12:15:36 -08:00
Bas Nijholt
708e09a8cc Show target host when starting services 2025-12-14 12:09:07 -08:00
Bas Nijholt
04154b84f6 Add tests for network and path checking
- test_traefik: Tests for parse_external_networks()
- test_ssh: Tests for check_paths_exist() and check_networks_exist()
2025-12-14 12:08:35 -08:00