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

Improve ports parsing #418

Closed
wants to merge 5 commits into from
Closed

Conversation

hirochri
Copy link

@hirochri hirochri commented Dec 9, 2019

Before this PR

This PR fixes: #411
TLDR: Getting port information for various services depends heavily on well white-spaced output from docker-compose ps <service_name> and regex, however this quickly breaks when the ps command output gets truncated as more information gets added to the ps output (health checks, etc).

After this PR

Instead of applying a regex to unreliable output from docker-compose ps <service_name> to get port information, we now:

  1. Get the container ID for the service by calling
    docker-compose ps -q <service_name>
  2. Grab only the port information by calling
    docker ps --no-trunc --format {{.Ports}} --filter id=<container_id>
  3. Apply the regex to the port information string -> get ports

This approach uses docker commands to do more heavily lifting and only return the specific information (ports) that we care about

==COMMIT_MSG==
Improve port parsing by leveraging more specific docker commands.
==COMMIT_MSG==

Possible downsides?

There is technically a dev break because I modified one of the DefaultDockerCompose constructors to take in a DockerExecutable.

@changelog-app
Copy link

changelog-app bot commented Dec 9, 2019

Generate changelog in changelog/@unreleased

Type

  • Feature
  • Improvement
  • Fix
  • Break
  • Deprecation
  • Manual task
  • Migration

Description

Check the box to generate changelog(s)

  • Generate changelog entry

@hirochri hirochri changed the title Improved ports parsing Improve ports parsing Dec 9, 2019
@hirochri hirochri marked this pull request as ready for review December 9, 2019 08:38
@hirochri
Copy link
Author

hirochri commented Dec 9, 2019

This one is ready for review @CRogers!

We need to re-trigger changelog-bot somehow, it should be improvement and break with the message Improve port parsing by leveraging more specific docker commands.

public static Ports parseFromDockerComposePs(String psOutput, String dockerMachineIp) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(psOutput), "No container found");
Matcher matcher = PORT_PATTERN.matcher(psOutput);
public static Ports parseFromPortInformation(String portInformation, String dockerMachineIp) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately nearly everything in DCR is public rather than package-private - so we should do some quick github searches to find out if anyone is using this internally or externally before making such a breaking change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fortunately in this case it does look safe, but worth bearing in mind!

Copy link
Author

Choose a reason for hiding this comment

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

Ah yeah, missed that one, sorry. Can include explicit comments about usage / impact of the break in the future

return psOutput;
private static ErrorHandler swallowingServiceDoesNotExist() {
return (exitCode, output, commandName, commands) -> {
if (exitCode == 1 && output.isEmpty()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why exit code 1 and not all exit codes? Will this silently fail if another exit code is thrown?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah this is pretty specific, its really only trying to add debug information for when docker can't find a service

~/code/foundry-academy-backend
$ docker-compose ps some_service
ERROR: No such service: some_service
~/code/foundry-academy-backend
$ echo $?
1

Seems it would be more proper for this function to check for various failure exit codes and throw an exception explicitly, while still providing output with suggestions around what the potential failure mode was?

String serviceName = commands[commands.length - 1];

log.warn("It looks like `{}` failed.", fullCommand);
log.warn("This probably happened because no `{}` service exists.", serviceName);
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this throw rather than silently continue? I imagine we can't recover from this?

Copy link
Author

Choose a reason for hiding this comment

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

If that output is produced, the command will have failed with empty output and then will trigger an exception right after it here: https://github.com/palantir/docker-compose-rule/pull/418/files#diff-cf7a91b7706a65a0c4cc650e69cf5d81R242

I agree that maybe a little misleading and we could clarify how swallowingServiceDoesNotExist handles the case

this.command = new Command(rawExecutable, log::trace);
public DefaultDockerCompose(
DockerComposeExecutable dockerComposeRawExecutable,
DockerExecutable dockerRawExecutable,
Copy link
Contributor

Choose a reason for hiding this comment

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

This also seems safe from a brief github search (I think 1 person has used it externally and none internally)

Copy link
Author

Choose a reason for hiding this comment

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

Yeah it seems reasonable enough, will add comments about break-impact next time!

}

@Test
public void parse_the_ps_output_on_ports() throws IOException, InterruptedException {
public void get_correct_ports() throws IOException, InterruptedException {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure about the value of this test - it mocks out a lot of behaviour and I wonder if an integeration test against docker or just testing the parsing directly would be more valuable.

Copy link
Author

Choose a reason for hiding this comment

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

I could trade this one out for an integration test, it would be easy enough to create a docker-compose.yml with various port setups and then check all the parsing without mocking. Will add that

}

@Test
public void attempt_to_get_ports_but_all_ports_are_open_for_container() throws IOException, InterruptedException {
Copy link
Contributor

Choose a reason for hiding this comment

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

Again here there is so much mocking I'm not sure what this is actually testing?

Copy link
Author

Choose a reason for hiding this comment

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

Will move to an integration test, but this one checks if you specified no ports for your container. An integration test should make this more clear

@hirochri
Copy link
Author

Swapped out the ports unit tests for integration tests. Not sure why the DockerComposeManagerNativeHealthcheckIntegrationTest integration test flaked this time.. Will address if it continues to fail, could you potentially trigger a re-run please?

Otherwise, will fix the error handling mentioned above with whatever we agree upon

@CRogers CRogers self-requested a review December 11, 2019 17:58
@CRogers
Copy link
Contributor

CRogers commented Jan 9, 2020

While I think this is nicer from a code point of view, it does have a couple of breaks (including using docker as well as docker-compose for the default code path, which should be fine but you never know), and since #424 has fixed the same problem I'm going to close it out for now.

@CRogers CRogers closed this Jan 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Port matching is breaks when docker-compose ps output changes
2 participants