Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Death Note :) #545

Merged
merged 9 commits into from
Jan 27, 2018
Merged

Death Note :) #545

merged 9 commits into from
Jan 27, 2018

Conversation

bsideup
Copy link
Member

@bsideup bsideup commented Jan 15, 2018

Start a helper "Ryuk" container to make sure that we clean the containers after the execution even if the JVM was "kill -9"ed.

Based on https://github.com/bsideup/moby-ryuk and uses my public automated build for now:
https://hub.docker.com/r/bsideup/moby-ryuk/builds/bhcmbnqyhtnvcqg8ijvnh6n/

Will move to TC org & hub once we get a name

@@ -178,22 +174,6 @@ private void checkMountableFile(DockerClient dockerClient, String id) {
}
}

private void checkExposedPort(String hostIpAddress, DockerClient dockerClient, String id) {
Copy link
Member Author

Choose a reason for hiding this comment

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

this check is not needed anymore, Ryuk demands a connectivity hence implicitly checks for the exposed port

@@ -95,7 +102,7 @@ public DockerClient client() {
log.info("Docker host IP address is {}", hostIpAddress);
DockerClient client = strategy.getClient();

if (!preconditionsChecked) {
Copy link
Member Author

Choose a reason for hiding this comment

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

had to change the name because it's not just preconditionsChecked anymore

@@ -93,6 +93,7 @@ public DockerComposeContainer(String identifier, List<File> composeFiles) {

// Use a unique identifier so that containers created for this compose environment can be identified
this.identifier = identifier;
project = identifier + Base58.randomString(6).toLowerCase();
Copy link
Member Author

Choose a reason for hiding this comment

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

without this change, compose.start(); compose.stop(); compose.start() would use the same randomIndentifier and might lead to some unpredictable side effects

Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to move this code into the starting() method and remove the duplicate line (245) in finished()? Else we should wrap this line in a private method generateProjectName(String identifier)

@@ -165,38 +166,15 @@ private void applyScaling() {
}

private void registerContainersForShutdown() {
// Ensure that all service containers that were launched by compose will be killed at shutdown
Copy link
Member Author

Choose a reason for hiding this comment

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

😍

Copy link
Member

Choose a reason for hiding this comment

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

Awesome 🗡️

Copy link
Member

Choose a reason for hiding this comment

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

✂️ 😄


String ryukContainerId = client.createContainerCmd(ryukImage)
.withHostConfig(new HostConfig() {
@JsonProperty("AutoRemove")
Copy link
Member Author

Choose a reason for hiding this comment

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

docker-java is behind, but this flag will remove the container if it stops (and it will stop when the cleanup happen)

Copy link
Member

Choose a reason for hiding this comment

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

Aha, I was wondering what would remove this container 😄

@bsideup bsideup added this to the 1.6.0 milestone Jan 15, 2018
private static final String TINY_IMAGE = TestcontainersConfiguration.getInstance().getTinyImage();
private static DockerClientFactory instance;

// Cached client configuration
private DockerClientProviderStrategy strategy;
private boolean preconditionsChecked = false;
private boolean initialized = false;
Copy link
Member

Choose a reason for hiding this comment

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

This boolean is of course false by default, or did you want to make it explicitly?

Copy link
Member Author

Choose a reason for hiding this comment

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

I just renamed the variable :) But yes, explicit false helps to understand the logic

@@ -95,7 +102,7 @@ public DockerClient client() {
log.info("Docker host IP address is {}", hostIpAddress);
DockerClient client = strategy.getClient();

if (!preconditionsChecked) {
if (!initialized) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we can encapsulate the following block like:

if (!initialized) {
  initialize();
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's not do it in this PR.

Copy link
Member

Choose a reason for hiding this comment

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

No problem, but why not? 😉

Copy link
Member Author

Choose a reason for hiding this comment

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

because it's out of scope, and if somebody submits another PR where they change DockerClientFactory, but we didn't merge "Death Note" PR yet, it will create more conflicts.
I'm happy to extract method as a follow up, or before, or in parallel, but don't want to increase the scope of this change :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Also think about reverts in case we discover some major bug :)

Copy link
Member

Choose a reason for hiding this comment

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

Yes okay, makes sense 🙂

@@ -165,38 +166,15 @@ private void applyScaling() {
}

private void registerContainersForShutdown() {
// Ensure that all service containers that were launched by compose will be killed at shutdown
Copy link
Member

Choose a reason for hiding this comment

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

Awesome 🗡️

@@ -93,6 +93,7 @@ public DockerComposeContainer(String identifier, List<File> composeFiles) {

// Use a unique identifier so that containers created for this compose environment can be identified
this.identifier = identifier;
project = identifier + Base58.randomString(6).toLowerCase();
Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to move this code into the starting() method and remove the duplicate line (245) in finished()? Else we should wrap this line in a private method generateProjectName(String identifier)

@@ -464,7 +462,12 @@ private void applyConfiguration(CreateContainerCmd createCommand) {
createCommand.withPrivileged(privilegedMode);
}

createCommand.withLabels(Collections.singletonMap("org.testcontainers", "true"));
createContainerCmdModifiers.forEach(hook -> hook.accept(createCommand));
Copy link
Member

Choose a reason for hiding this comment

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

Why do you have to do this now?

Copy link
Member Author

Choose a reason for hiding this comment

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

just moved the call from another place because we must add our labels after user sets his own

public final class ResourceReaper {

private static final Logger LOGGER = LoggerFactory.getLogger(ResourceReaper.class);

private static final List<List<Map.Entry<String, String>>> REGISTERED_FILTERS = new ArrayList<>();
Copy link
Member

Choose a reason for hiding this comment

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

Nitpicking, but I would not write this variable in capital letters, since the collection is mutable.

.withName("tc-ryuk-" + DockerClientFactory.SESSION_ID)
.withLabels(Collections.singletonMap(DockerClientFactory.TESTCONTAINERS_LABEL, "true"))
.withBinds(
new Bind("/var/run/docker.sock", new Volume("/var/run/docker.sock")),
Copy link
Member

Choose a reason for hiding this comment

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

I think for Docker for Windows, we need to add a leading slash here 😞 (that's what we also did in ContainerisedDockerCompose). Also see this SO answer (without real explanation) 😆 https://stackoverflow.com/questions/36765138/bind-to-docker-socket-on-windows/41005007#41005007

Copy link
Member Author

Choose a reason for hiding this comment

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

weird, but nice catch :) Will do

REGISTERED_FILTERS.notifyAll();
}
}

/**
* Register a container to be cleaned up, either on explicit call to stopAndRemoveContainer, or at JVM shutdown.
Copy link
Member

Choose a reason for hiding this comment

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

Shall we remove this method now?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, it's public. We can not remove it now

Copy link
Member

@rnorth rnorth left a comment

Choose a reason for hiding this comment

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

Nice! Just a few queries/requests then I think it's good to merge!


MountableFile mountableFile = MountableFile.forClasspathResource(this.getClass().getName().replace(".", "/") + ".class");
String ryukContainerId = ResourceReaper.start(hostIpAddress, client);
log.info("Ryuk started");
Copy link
Member

Choose a reason for hiding this comment

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

Super-trivial, but please could we change the message a bit for people who don't/won't grok the name? Something like "Ryuk started - will monitor and terminate Testcontainers containers on JVM exit" perhaps?

It's a bit wordy, but less mysterious.

@@ -165,38 +166,15 @@ private void applyScaling() {
}

private void registerContainersForShutdown() {
// Ensure that all service containers that were launched by compose will be killed at shutdown
Copy link
Member

Choose a reason for hiding this comment

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

✂️ 😄

})
.withExposedPorts(new ExposedPort(8080))
.withPublishAllPorts(true)
.withName("tc-ryuk-" + DockerClientFactory.SESSION_ID)
Copy link
Member

Choose a reason for hiding this comment

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

Nice to name the container 😄
Please could we just expand tc to testcontainers though? It's just a thing that people can google more easily if they're wondering what this container is.


String ryukContainerId = client.createContainerCmd(ryukImage)
.withHostConfig(new HostConfig() {
@JsonProperty("AutoRemove")
Copy link
Member

Choose a reason for hiding this comment

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

Aha, I was wondering what would remove this container 😄

}
}
},
"tc-ryuk"
Copy link
Member

Choose a reason for hiding this comment

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

Same as above, please could you expand tc to testcontainers for googlability?

@bsideup
Copy link
Member Author

bsideup commented Jan 22, 2018

@rnorth done 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants