Skip to content

Conversation

@jglogan
Copy link
Contributor

@jglogan jglogan commented Jun 21, 2025

See discussion below for example. For multiple network interfaces in a single container we'll want to integrate against a containerization that includes apple/containerization#156.

The change bumps the containerization dependency to 0.2.0 and addresses the breaking API changes.

% container network
OVERVIEW: Manage container networks

USAGE: container network <subcommand>

OPTIONS:
  --version               Show the version.
  -h, --help              Show help information.

SUBCOMMANDS:
  create                  Create a new network
  delete, rm              Delete one or more networks
  list, ls                List networks
  inspect                 Display information about one or more networks

  See 'container help network <subcommand>' for detailed help.

@jglogan jglogan force-pushed the users/jglogan/container-network branch from 3b03f04 to 823a6ab Compare June 21, 2025 00:01
return PluginLoader(pluginDirectories: pluginDirectories, pluginFactories: pluginFactories, defaultResourcePath: statePath, log: log)
}()

func validate() throws {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: no changes...just reordered private functions to the end of the compilation unit

@jglogan jglogan force-pushed the users/jglogan/container-network branch from 823a6ab to b3eb6d5 Compare June 23, 2025 20:57
@jglogan
Copy link
Contributor Author

jglogan commented Jun 26, 2025

Example usage (mistakenly posted to related container PR, moved here):

% container system start
Verifying apiserver is running...
% container network create foo
foo
% container network ls
NETWORK  STATE    SUBNET
default  running  192.168.64.0/24
foo      running  192.168.65.0/24
% container run -d --name web-default --network default --rm python:slim python3 -m http.server --bind 0.0.0.0 8000
web-default                      
% container run -d --name web-foo --network foo --rm python:slim python3 -m http.server --bind 0.0.0.0 8000        
web-foo                          
% curl http://web-default.test:8000
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
...
</body>
</html>
% curl http://web-foo.test:8000
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
...
</body>
</html>
% container network rm foo
Error: internalError: "delete failed for one or more networks: ["foo"]"
% container stop web-foo
web-foo
% container network rm foo
foo
%

@jglogan
Copy link
Contributor Author

jglogan commented Jun 27, 2025

Here's the interface info for a container attached to two networks:

# ip addr 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 1280 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,UP,LOWER_UP> mtu 1280 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 16:9d:c1:ff:2c:8c brd ff:ff:ff:ff:ff:ff
    inet 192.168.64.2/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fd47:1444:7a25:889c:149d:c1ff:feff:2c8c/64 scope global dynamic mngtmpaddr 
       valid_lft 2591912sec preferred_lft 604712sec
    inet6 fe80::149d:c1ff:feff:2c8c/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,UP,LOWER_UP> mtu 1280 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 3a:ca:72:23:77:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.65.2/24 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fd01:b7b1:c35b:1f82:38ca:72ff:fe23:7780/64 scope global dynamic mngtmpaddr 
       valid_lft 2591912sec preferred_lft 604712sec
    inet6 fe80::38ca:72ff:fe23:7780/64 scope link 
       valid_lft forever preferred_lft forever

# ip route
default via 192.168.64.1 dev eth0 
192.168.64.0/24 dev eth0 proto kernel scope link src 192.168.64.2 
192.168.65.0/24 dev eth1 proto kernel scope link src 192.168.65.2 

@jglogan jglogan force-pushed the users/jglogan/container-network branch from 83fe1fb to ae054c5 Compare June 27, 2025 03:15
crosbymichael pushed a commit to apple/containerization that referenced this pull request Jun 27, 2025
Here we implement the mechanism for ensuring that `container` doesn't
set up two default routes on containers that connect to multiple
networks. We'll implement the policy in apple/container#243.
Comment on lines 32 to 34
defer {

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this meant to be deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be deleted, but it prompted me to look over the test once more and I think what might have happened here was that I had some network cleanup code in a defer, but also I needed to delete the network at the start of the test to ensure a known initial condition.

I think it'd be good to do a belt and suspenders for the network cleanup, so I'm testing a change where I defer delete the network at the end of the test, and also delete the network at the start.

@jglogan jglogan force-pushed the users/jglogan/container-network branch from ae054c5 to 7643d55 Compare June 27, 2025 19:39
let client = getClient()
defer { _ = client.shutdown() }
var retriesRemaining = Self.retries
retryLoop: while retriesRemaining > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we instead have a boolean indicating success? So then the while loop changes to

while retriesRemaining > 0 && !success {
...
}

Copy link
Contributor Author

@jglogan jglogan Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can see how that coalesces all the decision making in a single place. I'm modifying the test already so let me make that change.

My motivation for the original pattern is that I try to avoid var unless I absolutely need it.

Copy link
Contributor Author

@jglogan jglogan Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other thing here is that we should never see anything but a 200 if we get an HTTP response, so I think we can #require(.ok) here and get rid of the labeled break as well.

@jglogan jglogan force-pushed the users/jglogan/container-network branch 2 times, most recently from e1a92c9 to e60da1c Compare June 27, 2025 20:41
}
retriesRemaining -= 1
}
#expect(success, "Request to \(url) failed after \(Self.retries) retries")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible we broke out before the full self.retries value. This should be self.retries - retriesRemaining.

Copy link
Contributor

@katiewasnothere katiewasnothere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comment on the test, otherwise lgtm :)

@jglogan jglogan force-pushed the users/jglogan/container-network branch from e60da1c to d9d9d59 Compare June 27, 2025 20:56
@katiewasnothere katiewasnothere merged commit 3b5c253 into apple:main Jun 27, 2025
2 checks passed
@jglogan jglogan deleted the users/jglogan/container-network branch July 4, 2025 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants