tests/16-render.sh runs tmux, zellij, and the TUI in xterm on Xvfb, takes screenshots, and reads them back with tesseract: remote prompts in all panes, borders and titles with the hosts, [SYNC] appearing and disappearing, panes side by side, broadcast output in every pane and input in one pane only without it, windows split by panes_per_window, the status bar, and TUI marks. Screenshots stay in testenv/.artifacts. OCR reads three preprocessing variants (plain, stretched for dim gray, brightest channel for colored text) and normalizes characters that DejaVu Sans Mono makes ambiguous (1/l, C/(). The screenshots showed tmux cutting the session name in the status bar to "[netssh-pv"; netssh multi now widens status-left-length for its own session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
212 lines
5.4 KiB
YAML
212 lines
5.4 KiB
YAML
# netssh test environment — local only, not used by CI/CD. See testenv/README.md.
|
|
#
|
|
# public 10.231.0.0/24 + fd00:30::/64 client, NetBox x2, bastion, static host, IPv6 host
|
|
# mgmt 10.231.1.0/24 client, Proxmox nodes (mgmt0), lab hosts
|
|
# prod 10.231.2.0/24 bastion, Proxmox nodes (eth0), VMs — not reachable from the client
|
|
name: netssh-test
|
|
|
|
x-netbox: &netbox
|
|
image: netboxcommunity/netbox:v4.7.4-5.1.1
|
|
depends_on:
|
|
postgres: {condition: service_healthy}
|
|
redis: {condition: service_healthy}
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "curl -sf http://localhost:8080/login/ >/dev/null"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 60
|
|
start_period: 60s
|
|
|
|
x-netbox-env: &netbox-env
|
|
DB_HOST: postgres
|
|
DB_USER: netbox
|
|
DB_PASSWORD: netbox
|
|
REDIS_HOST: redis
|
|
SECRET_KEY: netssh-test-environment-secret-key-0123456789-abcdefghijklmnopqrstuvwxyz
|
|
API_TOKEN_PEPPER_1: netssh-test-environment-pepper-0123456789-abcdefghijklmnop
|
|
SUPERUSER_NAME: admin
|
|
SUPERUSER_EMAIL: admin@example.com
|
|
SUPERUSER_PASSWORD: admin
|
|
SUPERUSER_API_KEY: netsshtest01
|
|
SUPERUSER_API_TOKEN: 0123456789abcdef0123456789abcdef01234567
|
|
SKIP_SUPERUSER: "false"
|
|
|
|
x-target: &target
|
|
build:
|
|
context: ..
|
|
dockerfile: testenv/targets/target.Dockerfile
|
|
image: netssh-test-target
|
|
volumes:
|
|
- ./.keys/authorized_keys:/keys/authorized_keys:ro
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:18-alpine
|
|
environment:
|
|
POSTGRES_USER: netbox
|
|
POSTGRES_PASSWORD: netbox
|
|
POSTGRES_DB: netbox
|
|
volumes:
|
|
- ./postgres-init.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
|
- postgres:/var/lib/postgresql
|
|
networks: [backend]
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U netbox"]
|
|
interval: 5s
|
|
retries: 30
|
|
|
|
redis:
|
|
image: redis:8-alpine
|
|
networks: [backend]
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
retries: 30
|
|
|
|
netbox-fsn:
|
|
<<: *netbox
|
|
hostname: netbox-fsn
|
|
environment:
|
|
<<: *netbox-env
|
|
DB_NAME: netbox_fsn
|
|
REDIS_DATABASE: "0"
|
|
REDIS_CACHE_DATABASE: "1"
|
|
ports: ["127.0.0.1:18000:8080"]
|
|
networks:
|
|
backend: {}
|
|
public: {ipv4_address: 10.231.0.20}
|
|
|
|
netbox-lab:
|
|
<<: *netbox
|
|
hostname: netbox-lab
|
|
environment:
|
|
<<: *netbox-env
|
|
DB_NAME: netbox_lab
|
|
REDIS_DATABASE: "2"
|
|
REDIS_CACHE_DATABASE: "3"
|
|
ports: ["127.0.0.1:18001:8080"]
|
|
networks:
|
|
backend: {}
|
|
public: {ipv4_address: 10.231.0.21}
|
|
|
|
# Jump host: the only way from the client into the prod network.
|
|
bastion:
|
|
<<: *target
|
|
hostname: bastion
|
|
networks:
|
|
public: {ipv4_address: 10.231.0.30, aliases: [bastion.hoster.test]}
|
|
prod: {ipv4_address: 10.231.2.30}
|
|
|
|
fsn1-pve1:
|
|
<<: *target
|
|
hostname: fsn1-pve1
|
|
networks:
|
|
mgmt: {ipv4_address: 10.231.1.11, aliases: [fsn1-pve1.hoster.test]}
|
|
prod: {ipv4_address: 10.231.2.11}
|
|
fsn1-pve2:
|
|
<<: *target
|
|
hostname: fsn1-pve2
|
|
networks:
|
|
mgmt: {ipv4_address: 10.231.1.12, aliases: [fsn1-pve2.hoster.test]}
|
|
prod: {ipv4_address: 10.231.2.12}
|
|
fsn1-pve3:
|
|
<<: *target
|
|
hostname: fsn1-pve3
|
|
networks:
|
|
mgmt: {ipv4_address: 10.231.1.13, aliases: [fsn1-pve3.hoster.test]}
|
|
prod: {ipv4_address: 10.231.2.13}
|
|
|
|
# VMs of cluster pve-fsn1: only in prod, so they need the bastion.
|
|
web1:
|
|
<<: *target
|
|
hostname: web1
|
|
networks:
|
|
prod: {ipv4_address: 10.231.2.21}
|
|
web2:
|
|
<<: *target
|
|
hostname: web2
|
|
networks:
|
|
prod: {ipv4_address: 10.231.2.22}
|
|
|
|
# NetBox instance "lab": a device and a VM named web1 like the fsn VM.
|
|
lab-db1:
|
|
<<: *target
|
|
hostname: lab-db1
|
|
networks:
|
|
mgmt: {ipv4_address: 10.231.1.41}
|
|
lab-web1:
|
|
<<: *target
|
|
hostname: lab-web1
|
|
networks:
|
|
mgmt: {ipv4_address: 10.231.1.42}
|
|
|
|
# Not in NetBox: tested as a static host.
|
|
legacy-box:
|
|
<<: *target
|
|
hostname: legacy-box
|
|
networks:
|
|
public: {ipv4_address: 10.231.0.50}
|
|
|
|
# In NetBox with an IPv6 primary address only.
|
|
v6-host:
|
|
<<: *target
|
|
hostname: v6-host
|
|
networks:
|
|
public: {ipv4_address: 10.231.0.60, ipv6_address: "fd00:30::60"}
|
|
|
|
client:
|
|
build:
|
|
context: ..
|
|
dockerfile: testenv/client.Dockerfile
|
|
image: netssh-test-client
|
|
hostname: client
|
|
init: true
|
|
volumes:
|
|
- ./.keys:/keys:ro
|
|
- ./.state:/state
|
|
- ./tests:/tests:ro
|
|
- ./.artifacts:/artifacts
|
|
networks:
|
|
public: {ipv4_address: 10.231.0.10, ipv6_address: "fd00:30::10"}
|
|
mgmt: {ipv4_address: 10.231.1.10}
|
|
|
|
# Fills both NetBox instances and writes /state/netssh.yaml, then exits.
|
|
seed:
|
|
image: netssh-test-client
|
|
depends_on:
|
|
client: {condition: service_started}
|
|
netbox-fsn: {condition: service_healthy}
|
|
netbox-lab: {condition: service_healthy}
|
|
volumes:
|
|
- ./.state:/state
|
|
- ./seed:/seed:ro
|
|
networks:
|
|
public: {}
|
|
command: ["python3", "/seed/seed.py"]
|
|
restart: "no"
|
|
|
|
# Fixed subnets outside Docker's default address pools (172.17-31.x, 192.168.x),
|
|
# so automatically numbered networks of other projects cannot collide.
|
|
networks:
|
|
backend:
|
|
ipam:
|
|
config:
|
|
- subnet: 10.231.3.0/24
|
|
public:
|
|
enable_ipv6: true
|
|
ipam:
|
|
config:
|
|
- subnet: 10.231.0.0/24
|
|
- subnet: fd00:30::/64
|
|
mgmt:
|
|
ipam:
|
|
config:
|
|
- subnet: 10.231.1.0/24
|
|
prod:
|
|
ipam:
|
|
config:
|
|
- subnet: 10.231.2.0/24
|
|
|
|
volumes:
|
|
postgres: {}
|