-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stats reporting in docker compose rule (#319)
* Copy over report api * Rename to event-api * Copy over code * Hook up before/after/setDescription * Delete unnecessary file * Use static shutdown reporter * Get something that seems to kind of post webhooks * Remove https for now * Parse and use reporting config file * Add parseable version for user agent * Remove enhanced-docker-compose-rule * Better name for webhook poster * Add some tests for config * Actually get http json poster working * Wiremock test for http code * Attempt to create integration test * Revert "Attempt to create integration test" This reverts commit 1915eb2. * Thread saftey lol * Add generated changelog entries * Helpful comment * Checkstyle * Test $VERSION behaviour * Make fake reporter rather than fake poster * Generalize out which env vars you want * Tests for PatternCollection * Revert "Revert "Attempt to create integration test"" This reverts commit f9526d0. * Fix integ test by manually triggering shutdown * Use empty test description * Remove needless keystores dep * Use optional flatMap * Delete JsonPoster * spotless * Remove meaningless name * Make test work by running out of process * Always run runRecorder.after() * Set connect timeout to be 1 sec * Better conjure def * Get rid of $VERSION * Put report API version in report itselft * NoOpReporter * Grab circle envvars by default and remove config option * Autorelease 1.1.0-rc1 * Revert "Autorelease 1.1.0-rc1" This reverts commit 7abd657.
- Loading branch information
Showing
25 changed files
with
1,155 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
type: feature | ||
feature: | ||
description: Reporting stats to a http endpoint is possible by creating a `.docker-compose-rule.yml` | ||
config file in the root of your project | ||
links: | ||
- https://github.com/palantir/docker-compose-rule/pull/319 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 99 additions & 0 deletions
99
.../integrationTest/java/com/palantir/docker/compose/reporting/ReportingIntegrationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.palantir.docker.compose.reporting; | ||
|
||
import static com.github.tomakehurst.wiremock.client.WireMock.post; | ||
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; | ||
import static com.github.tomakehurst.wiremock.client.WireMock.status; | ||
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; | ||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
|
||
import com.github.tomakehurst.wiremock.junit.WireMockRule; | ||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.io.CharStreams; | ||
import com.palantir.docker.compose.DockerComposeManager; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.Files; | ||
import java.nio.file.Paths; | ||
import java.util.concurrent.TimeUnit; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.TemporaryFolder; | ||
|
||
public class ReportingIntegrationTest { | ||
@Rule | ||
public final WireMockRule wireMockRule = new WireMockRule(); | ||
|
||
@Rule | ||
public final TemporaryFolder temporaryFolder = new TemporaryFolder(); | ||
|
||
// Run by test | ||
public static void main(String... args) throws IOException, InterruptedException { | ||
String testCodeWorkingDir = args[0]; | ||
|
||
DockerComposeManager dockerComposeManager = new DockerComposeManager.Builder() | ||
.file(Paths.get(testCodeWorkingDir, "src/test/resources/no-healthcheck.yaml") | ||
.toAbsolutePath() | ||
.toString()) | ||
.build(); | ||
|
||
try { | ||
dockerComposeManager.before(); | ||
} finally { | ||
dockerComposeManager.after(); | ||
} | ||
} | ||
|
||
@Test | ||
public void a_report_of_the_right_format_is_posted() throws IOException, InterruptedException { | ||
File config = temporaryFolder.newFile(".docker-compose-rule.yml"); | ||
Files.write(config.toPath(), ImmutableList.of( | ||
"reporting:", | ||
" url: http://localhost:" + wireMockRule.port() + "/some/path" | ||
), StandardCharsets.UTF_8); | ||
|
||
wireMockRule.stubFor(post("/some/path").willReturn(status(200))); | ||
|
||
// We start this in a new java subprocess, as the *intentional* use of shutdown hooks and reading config files | ||
// from the current working directory makes it very hard to run in process, since other instantiations of | ||
// DockerComposeManger may have already set statics | ||
Process process = new ProcessBuilder() | ||
.command("java", | ||
"-classpath", | ||
System.getProperty("java.class.path"), | ||
ReportingIntegrationTest.class.getCanonicalName(), | ||
System.getProperty("user.dir")) | ||
.directory(temporaryFolder.getRoot()) | ||
.start(); | ||
|
||
process.waitFor(30, TimeUnit.SECONDS); | ||
|
||
String stdout = streamToString(process.getInputStream()); | ||
System.out.println("stdout: " + stdout); | ||
System.out.println("stderr: " + streamToString(process.getErrorStream())); | ||
|
||
wireMockRule.verify(postRequestedFor(urlPathEqualTo("/some/path"))); | ||
} | ||
|
||
private String streamToString(InputStream inputStream) throws IOException { | ||
return CharStreams.toString(new InputStreamReader(inputStream, UTF_8)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
...core/src/main/java/com/palantir/docker/compose/configuration/DockerComposeRuleConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.palantir.docker.compose.configuration; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | ||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; | ||
import com.fasterxml.jackson.datatype.guava.GuavaModule; | ||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; | ||
import com.google.common.annotations.VisibleForTesting; | ||
import com.palantir.docker.compose.CustomImmutablesStyle; | ||
import com.palantir.docker.compose.reporting.ReportingConfig; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.Optional; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Stream; | ||
import one.util.streamex.StreamEx; | ||
import org.immutables.value.Value; | ||
|
||
@Value.Immutable | ||
@CustomImmutablesStyle | ||
@JsonDeserialize(as = ImmutableDockerComposeRuleConfig.class) | ||
public abstract class DockerComposeRuleConfig { | ||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(new YAMLFactory()) | ||
.registerModule(new Jdk8Module()) | ||
.registerModule(new GuavaModule()); | ||
public static final String CONFIG_FILENAME = ".docker-compose-rule.yml"; | ||
|
||
public abstract Optional<ReportingConfig> reporting(); | ||
|
||
public static class Builder extends ImmutableDockerComposeRuleConfig.Builder {} | ||
|
||
public static Builder builder() { | ||
return new Builder(); | ||
} | ||
|
||
public static Optional<DockerComposeRuleConfig> findAutomatically() { | ||
return findAutomaticallyFrom(new File(".")); | ||
} | ||
|
||
@VisibleForTesting | ||
static Optional<DockerComposeRuleConfig> findAutomaticallyFrom(File startDir) { | ||
// If current dir is /foo/bar/baz, we search for: | ||
// /foo/bar/baz/.docker-compose-rule.yml | ||
// /foo/bar/.docker-compose-rule.yml | ||
// /foo/.docker-compose-rule.yml | ||
// /.docker-compose-rule.yml | ||
Optional<File> configFile = dirAndParents(startDir) | ||
.map(dir -> new File(dir, CONFIG_FILENAME)) | ||
.findFirst(File::exists); | ||
|
||
return configFile.map(config -> { | ||
try { | ||
return OBJECT_MAPPER.readValue(config, DockerComposeRuleConfig.class); | ||
} catch (IOException e) { | ||
throw new RuntimeException("Couldn't deserialize config file", e); | ||
} | ||
}); | ||
} | ||
|
||
private static StreamEx<File> dirAndParents(File startDir) { | ||
return StreamEx.of(Stream.generate(new Supplier<Optional<File>>() { | ||
private Optional<File> dir = Optional.of(startDir.getAbsoluteFile()); | ||
|
||
@Override | ||
public Optional<File> get() { | ||
Optional<File> toReturn = dir; | ||
dir = dir.flatMap(directory -> Optional.ofNullable(directory.getParentFile())); | ||
return toReturn; | ||
} | ||
})) | ||
.takeWhile(Optional::isPresent) | ||
.map(Optional::get); | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
...compose-rule-core/src/main/java/com/palantir/docker/compose/reporting/ExceptionUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.palantir.docker.compose.reporting; | ||
|
||
import java.io.PrintWriter; | ||
import java.io.StringWriter; | ||
|
||
final class ExceptionUtils { | ||
private ExceptionUtils() {} | ||
|
||
public static String exceptionToString(Exception exception) { | ||
StringWriter stringWriter = new StringWriter(); | ||
PrintWriter printWriter = new PrintWriter(stringWriter); | ||
exception.printStackTrace(printWriter); | ||
return stringWriter.toString(); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
...compose-rule-core/src/main/java/com/palantir/docker/compose/reporting/HttpJsonPoster.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.palantir.docker.compose.reporting; | ||
|
||
import com.google.common.io.CharStreams; | ||
import java.io.InputStreamReader; | ||
import java.io.PrintWriter; | ||
import java.net.HttpURLConnection; | ||
import java.net.URL; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Optional; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
class HttpJsonPoster { | ||
private static final Logger log = LoggerFactory.getLogger(HttpJsonPoster.class); | ||
|
||
private final ReportingConfig reportingConfig; | ||
|
||
HttpJsonPoster(ReportingConfig reportingConfig) { | ||
this.reportingConfig = reportingConfig; | ||
} | ||
|
||
public void post(String json) { | ||
try { | ||
URL url = new URL(reportingConfig.url()); | ||
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); | ||
|
||
connection.setConnectTimeout(1_000); | ||
connection.setReadTimeout(10_000); | ||
|
||
connection.setRequestMethod("POST"); | ||
connection.setInstanceFollowRedirects(true); | ||
connection.setRequestProperty("Content-Type", "application/json"); | ||
|
||
String version = Optional.ofNullable(this.getClass().getPackage().getImplementationVersion()) | ||
.orElse("0.0.0"); | ||
connection.setRequestProperty("User-Agent", "docker-compose-rule/" + version); | ||
|
||
connection.setDoOutput(true); | ||
PrintWriter body = new PrintWriter(connection.getOutputStream()); | ||
body.println(json); | ||
body.close(); | ||
|
||
connection.connect(); | ||
|
||
int status = connection.getResponseCode(); | ||
|
||
if (status >= 400) { | ||
String error = CharStreams.toString(new InputStreamReader( | ||
connection.getErrorStream(), StandardCharsets.UTF_8)); | ||
|
||
throw new RuntimeException("Posting json failed. Error is: " + error); | ||
} | ||
|
||
connection.disconnect(); | ||
} catch (Exception e) { | ||
log.error("Failed to post report", e); | ||
} | ||
} | ||
} |
Oops, something went wrong.