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"}
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Java
- Estrellas
- 8.7k
- Forks
- 1.9k
- Merge medio
- 2 d 17 h
- PR fusionados (30 d)
- 9
Descripción
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
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con Network.java y ResourceReaper.java, especialmente con Network.getId(), Network.close() y removeNetworkById(), y luego inspecciona el caso existente en NetworkTest alrededor de la línea 100. Reproduce la secuencia con una red que todavía esté asociada a un contenedor y verifica que solicitar su ID después de la limpieza no provoque el conflicto reportado; añade una prueba de regresión para el comportamiento corregido del ciclo de vida.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- docker, java
- Área
- testing
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Estancado
- Claridad
- Bastante claro
- Aptitud para principiantes
- 35/100