Add bridge name column to --list-networks
list_networks_command() now includes each network's bridge name (recomputed via bridge_name(), not stored -- it's already a pure deterministic function of the network name), tab-aligned the same way as the existing name/kind/subnet columns, positioned before the trailing unaligned IPv6 column. Useful for correlating a network entry with its live host-side state (`ip link show <bridge>`, `iptables -t nat -L`) without recomputing the hash by hand. Verified as root via the doas rule against a fresh extern and intern network. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gv3s5jckJKzh6JkMoi2Akz
This commit is contained in:
@@ -177,8 +177,11 @@ Source layout (all under `src/`):
|
|||||||
the entry appended to `config.networks` and persisted; a network that
|
the entry appended to `config.networks` and persisted; a network that
|
||||||
fails to provision isn't saved. `list_networks_command()` reuses the same
|
fails to provision isn't saved. `list_networks_command()` reuses the same
|
||||||
independently-per-column tab-alignment scheme as `list_processes_command()`
|
independently-per-column tab-alignment scheme as `list_processes_command()`
|
||||||
(name/kind/subnet each aligned, then the IPv6 subnet — or `"(no ipv6)"` —
|
(name/kind/subnet/bridge each aligned — the bridge name recomputed via
|
||||||
appended unaligned as the trailing column, nothing follows it).
|
`bridge_name(network.name)` — `network_bridge.h` — rather than stored, since
|
||||||
|
it's already a pure deterministic function of the name — then the IPv6
|
||||||
|
subnet — or `"(no ipv6)"` — appended unaligned as the trailing column,
|
||||||
|
nothing follows it).
|
||||||
`delete_network_command()` currently only removes the config entry, the
|
`delete_network_command()` currently only removes the config entry, the
|
||||||
same as `delete_volume_command()`'s default (non-`-full`) behavior — it
|
same as `delete_volume_command()`'s default (non-`-full`) behavior — it
|
||||||
does not tear down the network's live bridge/namespace/iptables state (no
|
does not tear down the network's live bridge/namespace/iptables state (no
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ slocker-lite -V|--version
|
|||||||
| `--delete-volume <name>` | Remove a named volume from the config. The host directory is left untouched. |
|
| `--delete-volume <name>` | Remove a named volume from the config. The host directory is left untouched. |
|
||||||
| `--delete-volume-full <name>` | Like `--delete-volume`, but also recursively deletes the volume's host directory. |
|
| `--delete-volume-full <name>` | Like `--delete-volume`, but also recursively deletes the volume's host directory. |
|
||||||
| `-n, --network <name>` | Create/manage a persistent named network: requires exactly one of `--extern` (a real Linux bridge in the host's own namespace, with NAT/forwarding set up so containers on it reach the host's real network) or `--intern` (a bridge inside its own dedicated, routeless namespace, only reachable by other containers on the same network). `--subnet <cidr>` overrides the auto-allocated IPv4 range (`10.168.0.0/24`, incrementing per network); `--no-ipv6` disables (and `--subnet6 <cidr>` overrides) the auto-allocated IPv6 range, on by default. `--no-veth` forces the tap+relay join fallback even on a kernel that supports veth (useful for testing that path; it's otherwise chosen automatically whenever the running kernel lacks veth support). With `--run`, instead joins `<name>` to the container as its own `eth<N>` interface with an address from the network's subnet; repeatable, no membership limit. Root-only for now. **Known gap**: on a network joined via the tap+relay fallback, peer-to-peer connectivity works, but reaching the network's own gateway (and thus the outside, for `extern`) does not yet — root cause unconfirmed, see [`docs/networking-design.md`](docs/networking-design.md). |
|
| `-n, --network <name>` | Create/manage a persistent named network: requires exactly one of `--extern` (a real Linux bridge in the host's own namespace, with NAT/forwarding set up so containers on it reach the host's real network) or `--intern` (a bridge inside its own dedicated, routeless namespace, only reachable by other containers on the same network). `--subnet <cidr>` overrides the auto-allocated IPv4 range (`10.168.0.0/24`, incrementing per network); `--no-ipv6` disables (and `--subnet6 <cidr>` overrides) the auto-allocated IPv6 range, on by default. `--no-veth` forces the tap+relay join fallback even on a kernel that supports veth (useful for testing that path; it's otherwise chosen automatically whenever the running kernel lacks veth support). With `--run`, instead joins `<name>` to the container as its own `eth<N>` interface with an address from the network's subnet; repeatable, no membership limit. Root-only for now. **Known gap**: on a network joined via the tap+relay fallback, peer-to-peer connectivity works, but reaching the network's own gateway (and thus the outside, for `extern`) does not yet — root cause unconfirmed, see [`docs/networking-design.md`](docs/networking-design.md). |
|
||||||
| `--list-networks` | List all named networks (see `-n/--network`) with their kind, IPv4 subnet, and IPv6 subnet (or `(no ipv6)`). |
|
| `--list-networks` | List all named networks (see `-n/--network`) with their kind, IPv4 subnet, bridge name, and IPv6 subnet (or `(no ipv6)`). |
|
||||||
| `--delete-network <name>` | Remove a named network from the config. |
|
| `--delete-network <name>` | Remove a named network from the config. |
|
||||||
| `-p, --port-forward [<network>:]<host-port>:<container-port>` | With `--run`, forward a TCP port from the host into the container. `<network>` is optional, defaulting to the container's sole `--extern` network (an error if it joined more than one without specifying). Repeatable. Reachable via the host's real, externally-facing IP; `localhost`/loopback access has a known NAT-hairpinning limitation (see [`docs/networking-design.md`](docs/networking-design.md)). |
|
| `-p, --port-forward [<network>:]<host-port>:<container-port>` | With `--run`, forward a TCP port from the host into the container. `<network>` is optional, defaulting to the container's sole `--extern` network (an error if it joined more than one without specifying). Repeatable. Reachable via the host's real, externally-facing IP; `localhost`/loopback access has a known NAT-hairpinning limitation (see [`docs/networking-design.md`](docs/networking-design.md)). |
|
||||||
| `--list-processes` | List running `--run` sessions found by their pid files under `$XDG_STATE_HOME/slocker-lite/run/`, with their pid, container name, and status (`running` or `exited`). |
|
| `--list-processes` | List running `--run` sessions found by their pid files under `$XDG_STATE_HOME/slocker-lite/run/`, with their pid, container name, and status (`running` or `exited`). |
|
||||||
|
|||||||
+2
-2
@@ -233,8 +233,8 @@ void print_usage(const char* prog) {
|
|||||||
" --run, instead join <name> to the container;\n"
|
" --run, instead join <name> to the container;\n"
|
||||||
" may be repeated, no membership limit\n"
|
" may be repeated, no membership limit\n"
|
||||||
" --list-networks list all named networks (see -n/--network)\n"
|
" --list-networks list all named networks (see -n/--network)\n"
|
||||||
" with their kind, IPv4 subnet, and IPv6 subnet\n"
|
" with their kind, IPv4 subnet, bridge name,\n"
|
||||||
" (or \"(no ipv6)\")\n"
|
" and IPv6 subnet (or \"(no ipv6)\")\n"
|
||||||
" --delete-network <name>\n"
|
" --delete-network <name>\n"
|
||||||
" remove a named network from the config\n"
|
" remove a named network from the config\n"
|
||||||
" -p, --port-forward [<network>:]<host-port>:<container-port>\n"
|
" -p, --port-forward [<network>:]<host-port>:<container-port>\n"
|
||||||
|
|||||||
+10
-1
@@ -467,25 +467,31 @@ int list_networks_command(const AppConfig& config) {
|
|||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
std::vector<std::string> kinds;
|
std::vector<std::string> kinds;
|
||||||
std::vector<std::string> subnets;
|
std::vector<std::string> subnets;
|
||||||
|
std::vector<std::string> bridges;
|
||||||
names.reserve(config.networks.size());
|
names.reserve(config.networks.size());
|
||||||
kinds.reserve(config.networks.size());
|
kinds.reserve(config.networks.size());
|
||||||
subnets.reserve(config.networks.size());
|
subnets.reserve(config.networks.size());
|
||||||
|
bridges.reserve(config.networks.size());
|
||||||
size_t max_name_len = 0;
|
size_t max_name_len = 0;
|
||||||
size_t max_kind_len = 0;
|
size_t max_kind_len = 0;
|
||||||
size_t max_subnet_len = 0;
|
size_t max_subnet_len = 0;
|
||||||
|
size_t max_bridge_len = 0;
|
||||||
for (const auto& network : config.networks) {
|
for (const auto& network : config.networks) {
|
||||||
names.push_back(network.name);
|
names.push_back(network.name);
|
||||||
kinds.push_back(network.kind == NetworkKind::extern_ ? "extern" : "intern");
|
kinds.push_back(network.kind == NetworkKind::extern_ ? "extern" : "intern");
|
||||||
subnets.push_back(network.subnet);
|
subnets.push_back(network.subnet);
|
||||||
|
bridges.push_back(bridge_name(network.name));
|
||||||
max_name_len = std::max(max_name_len, names.back().size());
|
max_name_len = std::max(max_name_len, names.back().size());
|
||||||
max_kind_len = std::max(max_kind_len, kinds.back().size());
|
max_kind_len = std::max(max_kind_len, kinds.back().size());
|
||||||
max_subnet_len = std::max(max_subnet_len, subnets.back().size());
|
max_subnet_len = std::max(max_subnet_len, subnets.back().size());
|
||||||
|
max_bridge_len = std::max(max_bridge_len, bridges.back().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Independently tracked per column, same scheme as list_processes_command().
|
// Independently tracked per column, same scheme as list_processes_command().
|
||||||
size_t name_target_tabs = max_name_len / tab_width + 1;
|
size_t name_target_tabs = max_name_len / tab_width + 1;
|
||||||
size_t kind_target_tabs = max_kind_len / tab_width + 1;
|
size_t kind_target_tabs = max_kind_len / tab_width + 1;
|
||||||
size_t subnet_target_tabs = max_subnet_len / tab_width + 1;
|
size_t subnet_target_tabs = max_subnet_len / tab_width + 1;
|
||||||
|
size_t bridge_target_tabs = max_bridge_len / tab_width + 1;
|
||||||
|
|
||||||
for (size_t i = 0; i < config.networks.size(); ++i) {
|
for (size_t i = 0; i < config.networks.size(); ++i) {
|
||||||
size_t name_tabs_used = names[i].size() / tab_width;
|
size_t name_tabs_used = names[i].size() / tab_width;
|
||||||
@@ -494,8 +500,11 @@ int list_networks_command(const AppConfig& config) {
|
|||||||
size_t kind_tabs_needed = kind_target_tabs > kind_tabs_used ? kind_target_tabs - kind_tabs_used : 1;
|
size_t kind_tabs_needed = kind_target_tabs > kind_tabs_used ? kind_target_tabs - kind_tabs_used : 1;
|
||||||
size_t subnet_tabs_used = subnets[i].size() / tab_width;
|
size_t subnet_tabs_used = subnets[i].size() / tab_width;
|
||||||
size_t subnet_tabs_needed = subnet_target_tabs > subnet_tabs_used ? subnet_target_tabs - subnet_tabs_used : 1;
|
size_t subnet_tabs_needed = subnet_target_tabs > subnet_tabs_used ? subnet_target_tabs - subnet_tabs_used : 1;
|
||||||
fmt::print("{}{}{}{}{}{}{}\n", names[i], std::string(name_tabs_needed, '\t'), kinds[i],
|
size_t bridge_tabs_used = bridges[i].size() / tab_width;
|
||||||
|
size_t bridge_tabs_needed = bridge_target_tabs > bridge_tabs_used ? bridge_target_tabs - bridge_tabs_used : 1;
|
||||||
|
fmt::print("{}{}{}{}{}{}{}{}{}\n", names[i], std::string(name_tabs_needed, '\t'), kinds[i],
|
||||||
std::string(kind_tabs_needed, '\t'), subnets[i], std::string(subnet_tabs_needed, '\t'),
|
std::string(kind_tabs_needed, '\t'), subnets[i], std::string(subnet_tabs_needed, '\t'),
|
||||||
|
bridges[i], std::string(bridge_tabs_needed, '\t'),
|
||||||
config.networks[i].ipv6 ? config.networks[i].subnet6 : std::string("(no ipv6)"));
|
config.networks[i].ipv6 ? config.networks[i].subnet6 : std::string("(no ipv6)"));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user