Skip to content

Commit 95f94a4

Browse files
committed
Address gemini code review
1 parent 2554c71 commit 95f94a4

5 files changed

Lines changed: 51 additions & 7 deletions

File tree

nginx_proxy/WebServer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def disconnect(self, network, container, scope):
250250
if self.config_data.has_backend(container):
251251
try:
252252
backend = BackendTarget.from_container(self.client.containers.get(container))
253-
if not self.update_backend(backend):
253+
if not self.update_backend(backend, replace_existing=True):
254254
self.remove_backend(
255255
container
256256
) # remove_backend not implemented yet, using remove_container (it takes ID)
@@ -286,23 +286,23 @@ def connect(self, network, container, scope):
286286
# print(f"Skipping network connect for service task container {container}")
287287
return
288288
backend = BackendTarget.from_container(container_obj)
289-
self.update_backend(backend)
289+
self.update_backend(backend, replace_existing=True)
290290
except docker.errors.NotFound:
291291
return
292292
except (KeyboardInterrupt, SystemExit):
293293
raise
294294
except Exception as e:
295295
print(f"Error processing connect for container {container}: {e}", file=sys.stderr)
296296

297-
def update_backend(self, backend: BackendTarget):
297+
def update_backend(self, backend: BackendTarget, replace_existing: bool = False):
298298
"""
299299
Rescan the backend to detect changes. And update nginx configuration if necessary.
300300
:param backend: BackendTarget object
301301
:return: true if state change affected the nginx configuration else false
302302
"""
303303
try:
304304
existing_backend = self.config_data.has_backend(backend.id)
305-
if existing_backend and backend.type != "service":
305+
if existing_backend and backend.type != "service" and not replace_existing:
306306
return False
307307

308308
removed = None

tests/integration/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ def test_network(docker_client: docker.DockerClient, swarm_mode):
8585

8686
@pytest.fixture(
8787
scope="session",
88-
params=["ignore", "exclude", "enable", "strict"],
89-
ids=["swarm_ignore", "swarm_exclude", "swarm_enable", "swarm_strict"],
88+
params=["ignore", "exclude", "enable", "prefer-local", "strict"],
89+
ids=["swarm_ignore", "swarm_exclude", "swarm_enable", "swarm_prefer_local", "swarm_strict"],
9090
)
9191
def swarm_mode(request):
9292
return request.param

tests/integration/test_nginx_proxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def is_reachable(swarm_mode, backend_type):
1919
"""
2020
Determines if a backend should be reachable based on swarm mode and backend type.
2121
"""
22-
if swarm_mode in ("enable", "ignore"):
22+
if swarm_mode in ("enable", "ignore", "prefer-local"):
2323
return True
2424
if swarm_mode == "strict" and backend_type == "service":
2525
return True

tests/unit/test_web_server.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,22 @@ def test_update_backend_ignores_existing_container_backend(web_server):
134134
mock_throttle.assert_not_called()
135135

136136

137+
def test_update_backend_replaces_existing_container_backend_when_requested(web_server):
138+
web_server.networks = {"frontend": "frontend-id", "frontend-id": "frontend"}
139+
web_server.config_data = ProxyConfigData()
140+
existing = _backend_target("container1", "old.example.com", "172.18.0.2")
141+
updated = _backend_target("container1", "new.example.com", "172.18.0.3")
142+
web_server.register_backend(existing)
143+
144+
with patch.object(web_server.throttler, "throttle") as mock_throttle:
145+
changed = web_server.update_backend(updated, replace_existing=True)
146+
147+
assert changed is True
148+
assert web_server.config_data.getHost("old.example.com").isempty()
149+
assert web_server.config_data.getHost("new.example.com") is not None
150+
mock_throttle.assert_called_once()
151+
152+
137153
def test_update_backend_replaces_existing_service_backend(web_server):
138154
web_server.networks = {"frontend": "frontend-id", "frontend-id": "frontend"}
139155
web_server.config_data = ProxyConfigData()

tests/unit/test_webserver_events.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,34 @@ def test_webserver_remove_network(docker_client: DockerTestClient, nginx: DummyN
359359
expect_server_down(nginx, hostname)
360360

361361

362+
def test_webserver_disconnect_keeps_backend_when_another_proxy_network_remains(
363+
docker_client: DockerTestClient, webserver: WebServer, nginx: DummyNginx
364+
):
365+
container_name = "multi_reachable_network_container"
366+
hostname = "multi-reachable-network.example.com"
367+
env = {
368+
"VIRTUAL_HOST": hostname,
369+
}
370+
371+
alt_network = docker_client.networks.create("frontend_alt")
372+
webserver.networks[alt_network.id] = alt_network.name
373+
webserver.networks[alt_network.name] = alt_network.id
374+
375+
container = docker_client.containers.run("nginx:alpine", name=container_name, environment=env, network="frontend")
376+
time.sleep(0.2)
377+
378+
expect_server_up(nginx, hostname)
379+
380+
alt_network.connect(container.id)
381+
time.sleep(0.2)
382+
383+
frontend_network = docker_client.networks.get("frontend")
384+
frontend_network.disconnect(container.id)
385+
time.sleep(0.2)
386+
387+
expect_server_up(nginx, hostname)
388+
389+
362390
def test_webserver_recreate_same_name_container_with_different_host(docker_client: DockerTestClient, nginx: DummyNginx):
363391
container_name = "test_container"
364392
old_hostname = "old.recreate.example.com"

0 commit comments

Comments
 (0)