testcontainers / testcontainers/testcontainers-java
RemoveNetwork.close() never throws exception and keeps a network running causing Status 409: {"message":"network with name bdd49174-d251-4503-b1c2-d05c57206967 already exists"}
Nessuno ha ancora preso questa issue.
- Lingua principale
- Java
- Stelle
- 8.7k
- Fork
- 1.9k
- Merge medio
- 2g 17h
- PR unite (30g)
- 9
Descrizione
Hi,
first let me take this to thank you for the framework, it is super helpful to write docker based tests.
I found this issue in the latest version regarding how the network is closed, please if I'm not using properly the framework let me know 😄
In my setup I have 2 containers running with one network I created. The test manages the network, so no RYUK used here. After tests have run, I'm cleaning the resources i.e. containers and network and calling Network.close() for each container I shut down to let the network know the container left it.
But I get this error when I call Network.getId() after shutting down the second container to clean up the network:
`
com.github.dockerjava.api.exception.ConflictException: Status 409: {"message":"network with name bdd49174-d251-4503-b1c2-d05c57206967 already exists"}
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:245)
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.post(DefaultInvocationBuilder.java:125)
at org.testcontainers.shaded.com.github.dockerjava.core.exec.CreateNetworkCmdExec.execute(CreateNetworkCmdExec.java:27)
at org.testcontainers.shaded.com.github.dockerjava.core.exec.CreateNetworkCmdExec.execute(CreateNetworkCmdExec.java:12)
at org.testcontainers.shaded.com.github.dockerjava.core.exec.AbstrSyncDockerCmdExec.exec(AbstrSyncDockerCmdExec.java:21)
at org.testcontainers.shaded.com.github.dockerjava.core.command.AbstrDockerCmd.exec(AbstrDockerCmd.java:35)
at org.testcontainers.containers.Network$NetworkImpl.create(Network.java:92)
at org.testcontainers.containers.Network$NetworkImpl.getId(Network.java:63)
`
Here is why this error happens from what I found out.
When I shut down the first container, I then call Network.getId() to get the Network ID for logging and managing network IDs. This method does not only return an ID, but in fact it creates a network if the network does not exist.
public synchronized String getId() {
if (initialized.compareAndSet(false, true)) {
id = create();
}
return id;
}
The name getId() is misleading, as it means return an ID for this network and does not suggest a docker network ... command will in fact be invoked if the network does not exist, and that it will create a network.
Then I call Network.close(), which does this:
if (initialized.getAndSet(false)) {
ResourceReaper.instance().removeNetworkById(id);
}
Initialized is set to false, then the network is removed, but here is what happens in the removeNetworkById(...)
It calls removeNetwork(String id), which then fails silently if the network cannot be closed. In my scenario it cannot be closed as there is the second container still using it:
} catch (Exception e) {
LOGGER.trace("Error encountered removing network (name: {}) - it may not have been removed", network.getName());
}
The problem is that the network is now not initialized but still exists as it was not closed.
When I shut down the second container, then I call Network.getId() to log and manage the network ID, this method will run this:
`
if (initialized.compareAndSet(false, true)) {
id = create();
}
return id;
`
But because this network is not initialized anymore but still exists as the tests tried to close it, create() is called on an existing network and fail to do so rightfully with this error:
network with name bdd49174-d251-4503-b1c2-d05c57206967 already exists
And the tests fail.
I think the getId() should really just return the ID and a Network.create() method is needed that just does that, and the ResourceReaper.removeNetwork() should throw exceptions and not ignore them so one can deal with it as one needs to.
Add a test in the NetworkTest class that try to close a network which is still in use and ask for its ID through the getId() to trigger this issue.
The NetworkTest class did not catch this as it closes a Network that does not have containers attached to it.
https://github.com/testcontainers/testcontainers-java/blob/c381a64a6623fe71e95cfb73173907246a21e685/core/src/test/java/org/testcontainers/containers/NetworkTest.java#L100
lmk if I can help in reviewing or else.
Best,
Johnny
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia da Network.java e ResourceReaper.java, in particolare da Network.getId(), Network.close() e removeNetworkById(), quindi esamina il caso esistente in NetworkTest intorno alla riga 100. Riproduci la sequenza con una rete ancora collegata a un container e verifica che la richiesta del suo ID dopo la pulizia non attivi il conflitto segnalato; aggiungi un test di regressione per il comportamento corretto del ciclo di vita.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- docker, java
- Ambito
- testing
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100