feat: add --no-default-network flag to session create

Allow users to prevent automatic connection to the cubbi-network bridge
network when creating sessions, useful when only custom networks or
Docker's default bridge are needed.
This commit is contained in:
2026-02-05 19:00:53 -06:00
parent 78bde56cb4
commit b43db9320f
3 changed files with 68 additions and 21 deletions

View File

@@ -149,6 +149,11 @@ def create_session(
network: List[str] = typer.Option( network: List[str] = typer.Option(
[], "--network", "-N", help="Connect to additional Docker networks" [], "--network", "-N", help="Connect to additional Docker networks"
), ),
no_default_network: bool = typer.Option(
False,
"--no-default-network",
help="Don't connect to the default Cubbi network",
),
port: List[str] = typer.Option( port: List[str] = typer.Option(
[], [],
"--port", "--port",
@@ -419,6 +424,7 @@ def create_session(
ssh=ssh, ssh=ssh,
model=final_model, model=final_model,
domains=all_domains, domains=all_domains,
no_default_network=no_default_network,
) )
if session: if session:

View File

@@ -249,6 +249,7 @@ class ContainerManager:
model: Optional[str] = None, model: Optional[str] = None,
ssh: bool = False, ssh: bool = False,
domains: Optional[List[str]] = None, domains: Optional[List[str]] = None,
no_default_network: bool = False,
) -> Optional[Session]: ) -> Optional[Session]:
"""Create a new Cubbi session """Create a new Cubbi session
@@ -295,8 +296,9 @@ class ContainerManager:
if not session_name: if not session_name:
session_name = f"cubbi-{session_id}" session_name = f"cubbi-{session_id}"
# Ensure network exists # Ensure network exists (skip if user opted out of default network)
self._ensure_network() if not no_default_network:
self._ensure_network()
# Minimal environment variables # Minimal environment variables
env_vars = environment or {} env_vars = environment or {}
@@ -422,7 +424,7 @@ class ContainerManager:
) )
# Get network list # Get network list
network_list = [default_network] network_list = [] if no_default_network else [default_network]
# Process MCPs if provided # Process MCPs if provided
mcp_configs = [] mcp_configs = []
@@ -478,20 +480,16 @@ class ContainerManager:
pass pass
# Add user-specified networks # Add user-specified networks
# Default Cubbi network if no_default_network:
default_network = self.config_manager.config.docker.get( # Only use user-specified networks
"network", "cubbi-network" network_list = list(networks) if networks else []
) else:
# Get network list, ensuring default is first and no duplicates
# Get network list, ensuring default is first and no duplicates network_list = (
network_list_set = {default_network} [default_network] + [n for n in networks if n != default_network]
if networks: if networks
network_list_set.update(networks) else [default_network]
network_list = ( )
[default_network] + [n for n in networks if n != default_network]
if networks
else [default_network]
)
if networks: if networks:
for network in networks: for network in networks:
@@ -529,7 +527,7 @@ class ContainerManager:
"[yellow]Warning: Cannot use --domains with --network. Using domain restrictions only.[/yellow]" "[yellow]Warning: Cannot use --domains with --network. Using domain restrictions only.[/yellow]"
) )
networks = [] networks = []
network_list = [default_network] network_list = [] if no_default_network else [default_network]
# Create network-filter container # Create network-filter container
network_filter_name = f"cubbi-network-filter-{session_id}" network_filter_name = f"cubbi-network-filter-{session_id}"
@@ -656,9 +654,10 @@ class ContainerManager:
# Cannot set hostname when using network_mode # Cannot set hostname when using network_mode
else: else:
container_params["hostname"] = session_name container_params["hostname"] = session_name
container_params["network"] = network_list[ if network_list:
0 container_params["network"] = network_list[
] # Connect to the first network initially 0
] # Connect to the first network initially
container = self.client.containers.create(**container_params) container = self.client.containers.create(**container_params)

View File

@@ -295,6 +295,48 @@ def test_integration_session_create_with_single_port(isolate_cubbi_config):
container_manager.close_session(session.id, kill=True) container_manager.close_session(session.id, kill=True)
@requires_docker
def test_integration_session_create_no_default_network(
isolate_cubbi_config, docker_test_network
):
"""Test creating a session with no_default_network=True skips the default cubbi-network."""
session = None
try:
container_manager = isolate_cubbi_config["container_manager"]
# Create a session with no_default_network and a custom network
session = container_manager.create_session(
image_name="goose",
session_name=f"cubbi-test-no-default-net-{uuid.uuid4().hex[:8]}",
mount_local=False,
networks=[docker_test_network],
no_default_network=True,
)
assert session is not None
assert session.status == "running"
# Wait for container initialization to complete
init_success = wait_for_container_init(session.container_id)
assert init_success, "Container initialization timed out"
# Verify network connections
client = docker.from_env()
container = client.containers.get(session.container_id)
container_networks = container.attrs["NetworkSettings"]["Networks"]
# Container should be connected to the custom test network
assert docker_test_network in container_networks
# Container should NOT be connected to cubbi-network
assert "cubbi-network" not in container_networks
finally:
if session and session.container_id:
container_manager.close_session(session.id, kill=True)
@requires_docker @requires_docker
def test_integration_kill_vs_stop_speed(isolate_cubbi_config): def test_integration_kill_vs_stop_speed(isolate_cubbi_config):
"""Test that kill is faster than stop for container termination.""" """Test that kill is faster than stop for container termination."""