Skip to content

Commit

Permalink
Merge pull request #24 from reside-ic/network-alias-on-creation
Browse files Browse the repository at this point in the history
Network alias on creation
  • Loading branch information
M-Kusumgar authored Oct 20, 2023
2 parents d940f10 + db6f8f3 commit fe6611b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 37 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
runs-on: ubuntu-latest
env:
VAULT_TEST_GITHUB_PAT: ${{ secrets.VAULT_TEST_GITHUB_PAT }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
steps:
- uses: actions/checkout@v2

Expand All @@ -34,11 +35,11 @@ jobs:
- name: Tests
run: |
pytest --cov=src
pytest --cov=constellation
- name: Lint
run: |
pycodestyle . --exclude=.eggs
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
70 changes: 41 additions & 29 deletions constellation/constellation.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ def __init__(self, name, image, args=None,
self.image = image
self.args = args
self.mounts = mounts or []
self.ports = container_ports(ports)
self.ports_config = port_config(ports)
self.container_ports = container_ports(self.ports_config)
self.environment = environment
self.configure = configure
self.entrypoint = entrypoint
Expand All @@ -116,32 +117,36 @@ def start(self, prefix, network, volumes, data=None):
nm = self.name_external(prefix)
print("Starting {} ({})".format(self.name, str(self.image)))
mounts = [x.to_mount(volumes) for x in self.mounts]
x = cl.containers.create(str(self.image), self.args, name=nm,
detach=True, mounts=mounts,
network=self.network, ports=self.ports,
environment=self.environment,
entrypoint=self.entrypoint,
working_dir=self.working_dir,
labels=self.labels)

if self.ports_config:
# don't have to specify TCP vs UDP here because TCP is the default
host_config = cl.api.create_host_config(
mounts=mounts,
port_bindings=self.ports_config
)
else:
host_config = cl.api.create_host_config(mounts=mounts)

endpoint_config = cl.api.create_endpoint_config(aliases=[self.name])
networking_config = cl.api.create_networking_config({
f"{network.name}": endpoint_config
})
x_obj = cl.api.create_container(str(self.image), self.args, name=nm,
detach=True, labels=self.labels,
ports=self.container_ports,
environment=self.environment,
entrypoint=self.entrypoint,
working_dir=self.working_dir,
host_config=host_config,
networking_config=networking_config)
container_id = x_obj["Id"]
x = cl.containers.get(container_id)

if self.preconfigure:
self.preconfigure(x, data)

x.start()

# There is a bit of a faff here, because I do not see how we
# can get the container onto the network *and* alias it
# without having 'create' put it on a network first. This
# must be possible, but the SDK docs are a bit vague on the
# topic. So we create the container on the 'none' network,
# then disconnect it from that network, then attach it to our
# network with an appropriate alias (the docs suggest using an
# approch that uses the lower level api but I can't get that
# working).
if self.network == "none":
cl.networks.get("none").disconnect(x)
cl.networks.get(network.name).connect(x, aliases=[self.name])

x.reload()
if self.configure:
self.configure(x, data)

Expand Down Expand Up @@ -315,13 +320,20 @@ def to_mount(self, volumes):
**self.kwargs)


def int_into_tuple(i):
if isinstance(i, int):
return i, i
return i


def port_config(ports):
if not ports:
return None
tuple_ports = [int_into_tuple(p) for p in ports]
return {k: v for k, v in tuple_ports}


def container_ports(ports):
if not ports:
return None
ret = {}
for p in ports:
if type(p) is int:
p = (p, p)
p_container, p_host = p
ret["{}/tcp".format(p_container)] = p_host
return ret
return list(ports.keys())
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"vault_dev"]

setup(name="constellation",
version="1.2.3",
version="1.2.4",
description="Deploy scripts for constellations of docker containers",
long_description=long_description,
classifiers=[
Expand Down
37 changes: 32 additions & 5 deletions test/test_constellation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@ def rand_str(n=10, prefix="constellation-"):
return constellation.util.rand_str(n, prefix)


def test_container_ports_creates_ports_dictionary():
assert container_ports([]) is None
def test_ports_create_port_config_and_container_ports():
assert port_config([]) is None
assert port_config(None) is None
assert port_config([80]) == {80: 80}
assert port_config([80, 443]) == {80: 80, 443: 443}
assert port_config([(5432, 15432)]) == {5432: 15432}
assert port_config([(5432, 15432), 1]) == {5432: 15432, 1: 1}

assert container_ports(None) is None
assert container_ports([80]) == {"80/tcp": 80}
assert container_ports([80, 443]) == {"80/tcp": 80, "443/tcp": 443}
assert container_ports([(5432, 15432)]) == {"5432/tcp": 15432}
assert container_ports({80: 80}) == [80]
assert container_ports({80: 80, 443: 443}) == [80, 443]
assert container_ports({1: 2, 3: 4, 5: 5}) == [1, 3, 5]


def test_network():
Expand Down Expand Up @@ -158,6 +164,27 @@ def configure(container, data):
nw.remove()


def test_container_ports():
try:
nm = rand_str(prefix="")
cl = docker.client.from_env()
cl.images.pull("library/alpine:latest")
x = ConstellationContainer(nm, "library/alpine:latest",
ports=[80, (3000, 8080)])
nw = ConstellationNetwork(rand_str())
nw.create()
x.start("prefix", nw, None)
container_config = cl.api.inspect_container(f"prefix-{nm}")
port_bindings = container_config["HostConfig"]["PortBindings"]
assert port_bindings == {
"80/tcp": [{"HostIp": "", "HostPort": "80"}],
"3000/tcp": [{"HostIp": "", "HostPort": "8080"}],
}
finally:
x.stop("prefix", True)
nw.remove()


def test_container_pull():
ref = "library/hello-world:latest"
x = ConstellationContainer("hello", ref)
Expand Down

0 comments on commit fe6611b

Please sign in to comment.