io.github.microcks.testcontainers.MicrocksContainer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of microcks-testcontainers Show documentation
Show all versions of microcks-testcontainers Show documentation
Microcks Testcontainers Java library
The newest version!
/*
* Copyright The Microcks Authors.
*
* 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 io.github.microcks.testcontainers;
import io.github.microcks.testcontainers.model.Secret;
import io.github.microcks.testcontainers.model.TestResult;
import io.github.microcks.testcontainers.model.TestRequest;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.github.dockerjava.api.command.InspectContainerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
import org.testcontainers.shaded.com.github.dockerjava.core.MediaType;
import org.testcontainers.shaded.com.google.common.net.HttpHeaders;
import org.testcontainers.shaded.org.awaitility.Awaitility;
import org.testcontainers.shaded.org.awaitility.core.ConditionTimeoutException;
import org.testcontainers.utility.DockerImageName;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* Testcontainers implementation for main Microcks container.
* @author laurent
*/
public class MicrocksContainer extends GenericContainer {
/** Get a SL4J logger. */
private static final Logger log = LoggerFactory.getLogger(MicrocksContainer.class);
private static final String MICROCKS_FULL_IMAGE_NAME = "quay.io/microcks/microcks-uber";
private static final DockerImageName MICROCKS_IMAGE = DockerImageName.parse(MICROCKS_FULL_IMAGE_NAME);
private static final String HTTP_UPLOAD_LINE_FEED = "\r\n";
public static final int MICROCKS_HTTP_PORT = 8080;
public static final int MICROCKS_GRPC_PORT = 9090;
private static ObjectMapper mapper;
private Set snapshotsToImport;
private Set mainArtifactsToImport;
private Set secondaryArtifactsToImport;
private Set mainRemoteArtifactsToImport;
private Set secondaryRemoteArtifactsToImport;
private Set secrets;
/**
* Build a new MicrocksContainer with its container image name as string. This image must
* be compatible with quay.io/microcks/microcks-uber image.
* @param image The name (with tag/version) of Microcks Uber distribution to use.
*/
public MicrocksContainer(String image) {
this(DockerImageName.parse(image));
}
/**
* Build a new MicrocksContainer with its full container image name. This image must
* be compatible with quay.io/microcks/microcks-uber image.
* @param imageName The name (with tag/version) of Microcks Uber distribution to use.
*/
public MicrocksContainer(DockerImageName imageName) {
super(imageName);
imageName.assertCompatibleWith(MICROCKS_IMAGE);
withExposedPorts(MICROCKS_HTTP_PORT, MICROCKS_GRPC_PORT);
waitingFor(Wait.forLogMessage(".*Started MicrocksApplication.*", 1));
}
/**
* Provide paths to artifacts that will be imported as primary or main ones within the Microcks container
* once it will be started and healthy.
* @param artifacts A set of paths to artifacts that will be loaded as classpath resources
* @return self
*/
public MicrocksContainer withMainArtifacts(String... artifacts) {
if (mainArtifactsToImport == null) {
mainArtifactsToImport = new HashSet<>();
}
mainArtifactsToImport.addAll(Arrays.stream(artifacts).collect(Collectors.toList()));
return self();
}
/**
* Provide paths to artifacts that will be imported as secondary ones within the Microcks container
* once it will be started and healthy.
* @param artifacts A set of paths to artifacts that will be loaded as classpath resources
* @return self
*/
public MicrocksContainer withSecondaryArtifacts(String... artifacts) {
if (secondaryArtifactsToImport == null) {
secondaryArtifactsToImport = new HashSet<>();
}
secondaryArtifactsToImport.addAll(Arrays.stream(artifacts).collect(Collectors.toList()));
return self();
}
/**
* Provide urls to artifacts that will be imported as primary or main ones within the Microcks container
* once it will be started and healthy.
* @param remoteArtifactUrls A set of urls to artifacts that will be loaded as remote one
* @return self
*/
public MicrocksContainer withMainRemoteArtifacts(String... remoteArtifactUrls) {
if (mainRemoteArtifactsToImport == null) {
mainRemoteArtifactsToImport = new HashSet<>();
}
mainRemoteArtifactsToImport.addAll(Arrays.stream(remoteArtifactUrls).collect(Collectors.toList()));
return self();
}
/**
* Provide urls to artifacts that will be imported as secondary ones within the Microcks container
* once it will be started and healthy.
* @param remoteArtifactUrls A set of urls to artifacts that will be loaded as remote one
* @return self
*/
public MicrocksContainer withSecondaryRemoteArtifacts(String... remoteArtifactUrls) {
if (secondaryRemoteArtifactsToImport == null) {
secondaryRemoteArtifactsToImport = new HashSet<>();
}
secondaryRemoteArtifactsToImport.addAll(Arrays.stream(remoteArtifactUrls).collect(Collectors.toList()));
return self();
}
/**
* Provide paths to local repository snapshots that will be imported within the Microcks container
* once it will be started and healthy.
* @param snapshots A set of repository snapshots that will be loaded as classpath resources
* @return self
*/
public MicrocksContainer withSnapshots(String... snapshots) {
if (snapshotsToImport == null) {
snapshotsToImport = new HashSet<>();
}
snapshotsToImport.addAll(Arrays.stream(snapshots).collect(Collectors.toList()));
return self();
}
/**
* Provide Secret that should be imported in Microcks after startup.
* @param secret The description of a secret to access remote Git repotisory, test endpoint or broker.
* @return self
*/
public MicrocksContainer withSecret(Secret secret) {
if (secrets == null) {
secrets = new HashSet<>();
}
secrets.add(secret);
return self();
}
@Override
protected void containerIsStarted(InspectContainerResponse containerInfo) {
// Load snapshots before anything else.
if (snapshotsToImport != null && !snapshotsToImport.isEmpty()) {
snapshotsToImport.forEach(this::importSnapshot);
}
// Load remote artifacts before local ones.
if (mainRemoteArtifactsToImport != null && !mainRemoteArtifactsToImport.isEmpty()) {
mainRemoteArtifactsToImport.forEach((String remoteArtifactUrl) -> this.downloadArtifact(remoteArtifactUrl, true));
}
if (secondaryRemoteArtifactsToImport != null && !secondaryRemoteArtifactsToImport.isEmpty()) {
secondaryRemoteArtifactsToImport.forEach((String remoteArtifactUrl) -> this.downloadArtifact(remoteArtifactUrl, false));
}
// Load local ones that may override remote ones.
if (mainArtifactsToImport != null && !mainArtifactsToImport.isEmpty()) {
mainArtifactsToImport.forEach((String artifactPath) -> this.importArtifact(artifactPath, true));
}
if (secondaryArtifactsToImport != null && !secondaryArtifactsToImport.isEmpty()) {
secondaryArtifactsToImport.forEach((String artifactPath) -> this.importArtifact(artifactPath, false));
}
// Load secrets before remote artifacts as they may be needed for authentication.
if (secrets != null && !secrets.isEmpty()) {
secrets.forEach(this::createSecret);
}
}
/**
* Get the Http endpoint where Microcks can be accessed (you'd have to append '/api' to access APIs)
* @return The Http endpoint for talking to container.
*/
public String getHttpEndpoint() {
return String.format("http://%s:%s", getHost(), getMappedPort(MICROCKS_HTTP_PORT));
}
/**
* Get the exposed mock endpoint for a SOAP Service.
* @param service The name of Service/API
* @param version The version of Service/API
* @return A usable endpoint to interact with Microcks mocks.
*/
public String getSoapMockEndpoint(String service, String version) {
return String.format("%s/soap/%s/%s", getHttpEndpoint(), service, version);
}
/**
* Get the exposed mock endpoint for a REST API.
* @param service The name of Service/API
* @param version The version of Service/API
* @return A usable endpoint to interact with Microcks mocks.
*/
public String getRestMockEndpoint(String service, String version) {
return String.format("%s/rest/%s/%s", getHttpEndpoint(), service, version);
}
/**
* Get the exposed mock endpoint for a GRPC Service.
* @param service The name of Service/API
* @param version The version of Service/API
* @return A usable endpoint to interact with Microcks mocks.
*/
public String getGraphQLMockEndpoint(String service, String version) {
return String.format("%s/graphql/%s/%s", getHttpEndpoint(), service, version);
}
/**
* Get the exposed mock endpoint for a GRPC Service.
* @return A usable endpoint to interact with Microcks mocks.
*/
public String getGrpcMockEndpoint() {
return String.format("grpc://%s:%s", getHost(), getMappedPort(MICROCKS_GRPC_PORT));
}
/**
* Import an artifact as a primary or main one within the Microcks container.
* @param artifact The file representing artifact (OpenAPI, Postman collection, Protobuf, GraphQL schema, ...)
* @throws IOException If file cannot be read of transmission exception occurs.
* @throws MicrocksException If artifact cannot be correctly imported in container (probably malformed)
*/
public void importAsMainArtifact(File artifact) throws IOException, MicrocksException {
MicrocksContainer.importArtifact(getHttpEndpoint(), artifact, true);
}
/**
* Import an artifact as a secondary one within the Microcks container.
* @param artifact The file representing artifact (OpenAPI, Postman collection, Protobuf, GraphQL schema, ...)
* @throws IOException If file cannot be read of transmission exception occurs.
* @throws MicrocksException If artifact cannot be correctly imported in container (probably malformed)
*/
public void importAsSecondaryArtifact(File artifact) throws IOException, MicrocksException {
MicrocksContainer.importArtifact(getHttpEndpoint(), artifact, false);
}
/**
* Import a repository snapshot within the Microcks container.
* @param snapshot The file representing the Microcks repository snapshot
* @throws IOException If file cannot be read of transmission exception occurs.
* @throws MicrocksException If artifact cannot be correctly imported in container (probably malformed)
*/
public void importSnapshot(File snapshot) throws IOException, MicrocksException {
MicrocksContainer.importSnapshot(getHttpEndpoint(), snapshot);
}
/**
* Import an artifact as a primary or secondary one within the Microcks container. This may be a fallback to
* non-static {@code importArtifactAs...(File artifact)} method if you don't have direct access to the MicrocksContainer
* instance you want to import this artifact into.
* @param microcksContainerHttpEndpoint The Http endpoint where to reach running MicrocksContainer
* @param artifact The file representing artifact (OpenAPI, Postman collection, Protobuf, GraphQL schema, ...)
* @param mainArtifact Whether this artifact should be considered as main or secondary.
* @throws IOException If file cannot be read of transmission exception occurs.
* @throws MicrocksException If artifact cannot be correctly imported in container (probably malformed)
*/
public static void importArtifact(String microcksContainerHttpEndpoint, File artifact, boolean mainArtifact) throws IOException, MicrocksException {
if (!artifact.exists()) {
throw new IOException("Artifact " + artifact.getPath() + " does not exist or can't be read.");
}
URL url = new URL(microcksContainerHttpEndpoint + "/api/artifact/upload" + (mainArtifact ? "" : "?mainArtifact=false"));
HttpURLConnection httpConn = uploadFileToMicrocks(url, artifact, "application/octet-stream");
if (httpConn.getResponseCode() != 201) {
// Read response content for diagnostic purpose.
StringBuilder responseContent = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8))) {
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
responseContent.append(responseLine.trim());
}
}
// Disconnect Http connection.
httpConn.disconnect();
log.error("Artifact has not been correctly imported: {}", responseContent);
throw new MicrocksException("Artifact has not been correctly imported: " + responseContent);
}
// Disconnect Http connection.
httpConn.disconnect();
}
/**
* Import a repository snapshot within the Microcks container. This may be a fallback to
* non-static {@code importSnapshot(File artifact)} method if you don't have direct access to the MicrocksContainer
* instance you want to import this snapshot into.
* @param microcksContainerHttpEndpoint The Http endpoint where to reach running MicrocksContainer
* @param snapshot The file representing the Microcks repository snapshot
* @throws IOException If file cannot be read of transmission exception occurs.
* @throws MicrocksException If artifact cannot be correctly imported in container (probably malformed)
*/
public static void importSnapshot(String microcksContainerHttpEndpoint, File snapshot) throws IOException, MicrocksException {
if (!snapshot.exists()) {
throw new IOException("Snapshot " + snapshot.getPath() + " does not exist or can't be read.");
}
URL url = new URL(microcksContainerHttpEndpoint + "/api/import");
HttpURLConnection httpConn = uploadFileToMicrocks(url, snapshot, "application/json");
if (httpConn.getResponseCode() != 201) {
// Read response content for diagnostic purpose.
StringBuilder responseContent = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8))) {
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
responseContent.append(responseLine.trim());
}
}
// Disconnect Http connection.
httpConn.disconnect();
log.error("Snapshot has not been correctly imported: {}", responseContent);
throw new MicrocksException("Snapshot has not been correctly imported: " + responseContent);
}
// Disconnect Http connection.
httpConn.disconnect();
}
/**
* Launch a conformance test on an endpoint.
* @param testRequest The test specifications (API under test, endpoint, runner, ...)
* @return The final TestResult containing information on success/failure as well as details on test cases.
* @throws IOException If connection to Microcks container failed (no route to host, low-level network stuffs)
* @throws MicrocksException If Microcks fails creating a new test giving your request.
*/
public TestResult testEndpoint(TestRequest testRequest) throws IOException, MicrocksException {
return testEndpoint(getHttpEndpoint(), testRequest);
}
/**
* Launch a conformance test on an endpoint asynchronously.
* @param testRequest The test specifications (API under test, endpoint, runner, ...)
* @return A completable future that will allow to retrieve a TestResult once test is finished.
*/
public CompletableFuture testEndpointAsync(TestRequest testRequest) {
return testEndpointAsync(getHttpEndpoint(), testRequest);
}
/**
* Launch a conformance test on an endpoint asynchronously.
* @param microcksContainerHttpEndpoint The Http endpoint where to reach running MicrocksContainer
* @param testRequest The test specifications (API under test, endpoint, runner, ...)
* @return A completable future that will allow to retrieve a TestResult once test is finished.
*/
public static CompletableFuture testEndpointAsync(String microcksContainerHttpEndpoint, TestRequest testRequest) {
return CompletableFuture.supplyAsync(() -> {
try {
return MicrocksContainer.testEndpoint(microcksContainerHttpEndpoint, testRequest);
} catch (Exception e) {
throw new CompletionException(e);
}
});
}
/**
* Launch a conformance test on an endpoint. This may be a fallback to non-static {@code testEndpoint(TestRequest testRequest)}
* method if you don't have direct access to the MicrocksContainer instance you want to run this test on.
* @param microcksContainerHttpEndpoint The Http endpoint where to reach running MicrocksContainer
* @param testRequest The test specifications (API under test, endpoint, runner, ...)
* @return The final TestResult containing information on success/failure as well as details on test cases.
* @throws IOException If connection to Microcks container failed (no route to host, low-level network stuffs)
* @throws MicrocksException If Microcks fails creating a new test giving your request.
*/
public static TestResult testEndpoint(String microcksContainerHttpEndpoint, TestRequest testRequest) throws IOException, MicrocksException {
String requestBody = getMapper().writeValueAsString(testRequest);
// Build a new client on correct API endpoint.
URL url = new URL(microcksContainerHttpEndpoint + "/api/tests");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON.getMediaType());
httpConn.setDoOutput(true);
try (OutputStream os = httpConn.getOutputStream()) {
byte[] input = requestBody.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
StringBuilder responseContent = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8))) {
String responseLine;
while ((responseLine = br.readLine()) != null) {
responseContent.append(responseLine.trim());
}
}
if (httpConn.getResponseCode() == 201) {
httpConn.disconnect();
TestResult testResult = getMapper().readValue(responseContent.toString(), TestResult.class);
log.debug("Got Test Result: {}, now polling for progression", testResult.getId());
final String testResultId = testResult.getId();
try {
Awaitility.await()
.atMost(testRequest.getTimeout() + 1000, TimeUnit.MILLISECONDS)
.pollDelay(100, TimeUnit.MILLISECONDS)
.pollInterval(200, TimeUnit.MILLISECONDS)
.until(() -> !refreshTestResult(microcksContainerHttpEndpoint, testResultId).isInProgress());
} catch (ConditionTimeoutException timeoutException) {
log.info("Caught a ConditionTimeoutException for test on {}", testRequest.getTestEndpoint());
}
// Return the final result.
return refreshTestResult(microcksContainerHttpEndpoint, testResultId);
}
if (log.isErrorEnabled()) {
log.error("Couldn't launch on new test on Microcks with status {} ", httpConn.getResponseCode());
log.error("Error response body is {}", responseContent);
}
httpConn.disconnect();
throw new MicrocksException("Couldn't launch on new test on Microcks. Please check Microcks container logs");
}
/**
* Download a remote artifact as a primary or main one within the Microcks container.
* @param remoteArtifactUrl The URL to remote artifact (OpenAPI, Postman collection, Protobuf, GraphQL schema, ...)
* @throws ArtifactLoadException If artifact cannot be correctly downloaded in container (probably not found)
*/
public void downloadAsMainRemoteArtifact(String remoteArtifactUrl) throws ArtifactLoadException {
downloadArtifact(remoteArtifactUrl, true);
}
/**
* Download a remote artifact as a secondary one within the Microcks container.
* @param remoteArtifactUrl The URL to remote artifact (OpenAPI, Postman collection, Protobuf, GraphQL schema, ...)
* @throws ArtifactLoadException If artifact cannot be correctly downloaded in container (probably not found)
*/
public void downloadAsSecondaryRemoteArtifact(String remoteArtifactUrl) throws ArtifactLoadException {
downloadArtifact(remoteArtifactUrl, false);
}
private void importArtifact(String artifactPath, boolean mainArtifact) {
URL resource = Thread.currentThread().getContextClassLoader().getResource(artifactPath);
if (resource == null) {
resource = MicrocksContainer.class.getClassLoader().getResource(artifactPath);
if (resource == null) {
log.warn("Could not load classpath artifact: {}", artifactPath);
throw new ArtifactLoadException("Error while importing artifact: " + artifactPath);
}
}
try {
// Decode resource file path that may contain spaces converted into %20.
File resourceFile = new File(URLDecoder.decode(resource.getFile(), StandardCharsets.UTF_8.name()));
MicrocksContainer.importArtifact(getHttpEndpoint(), resourceFile, mainArtifact);
} catch (Exception e) {
log.error("Could not load classpath artifact: {}", artifactPath);
throw new ArtifactLoadException("Error while importing artifact: " + artifactPath, e);
}
}
private void downloadArtifact(String remoteArtifactUrl, boolean mainArtifact) throws ArtifactLoadException {
try {
// Use the artifact/download endpoint to download the artifact.
URL url = new URL(getHttpEndpoint() + "/api/artifact/download");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setRequestMethod("POST");
httpConn.setDoOutput(true);
String requestBody = "mainArtifact=" + mainArtifact + "&url=" + remoteArtifactUrl;
// Write the request body to the output stream of the connection
try (OutputStream os = httpConn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os))) {
writer.write(requestBody);
writer.flush();
}
if (httpConn.getResponseCode() != 201) {
// Read response content for diagnostic purpose.
StringBuilder responseContent = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8))) {
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
responseContent.append(responseLine.trim());
}
}
// Disconnect Http connection.
httpConn.disconnect();
log.error("Artifact has not been correctly downloaded: {}", responseContent);
throw new MicrocksException("Artifact has not been correctly downloaded: " + responseContent);
}
// Disconnect Http connection.
httpConn.disconnect();
} catch (Exception e) {
log.error("Could not load remote artifact: {}", remoteArtifactUrl);
throw new ArtifactLoadException("Error while importing remote artifact: " + remoteArtifactUrl, e);
}
}
private void importSnapshot(String snapshotPath) {
URL resource = Thread.currentThread().getContextClassLoader().getResource(snapshotPath);
if (resource == null) {
resource = MicrocksContainer.class.getClassLoader().getResource(snapshotPath);
if (resource == null) {
log.warn("Could not load classpath snapshot: {}", snapshotPath);
throw new ArtifactLoadException("Error while importing snasphot: " + snapshotPath);
}
}
try {
MicrocksContainer.importSnapshot(getHttpEndpoint(), new File(resource.getFile()));
} catch (Exception e) {
log.error("Could not load classpath snapshot: {}", snapshotPath);
throw new ArtifactLoadException("Error while importing snapshot: " + snapshotPath, e);
}
}
private void createSecret(Secret secret) {
try {
URL url = new URL(getHttpEndpoint() + "/api/secrets");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON.getMediaType());
httpConn.setRequestProperty(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.getMediaType());
httpConn.setDoOutput(true);
String requestBody = getMapper().writeValueAsString(secret);
try (OutputStream os = httpConn.getOutputStream()) {
byte[] input = requestBody.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
os.flush();
}
if (httpConn.getResponseCode() != 201) {
// Read response content for diagnostic purpose.
StringBuilder responseContent = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8))) {
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
responseContent.append(responseLine.trim());
}
}
// Disconnect Http connection.
httpConn.disconnect();
log.error("Secret has not been correctly created: {}", responseContent);
throw new MicrocksException("Secret has not been correctly created: " + responseContent);
}
// Disconnect Http connection.
httpConn.disconnect();
} catch (Exception e) {
log.warn("Error while creating Secret: {}", secret.getName());
throw new SecretCreationException("Error while creating Secret", e);
}
}
private static ObjectMapper getMapper() {
if (mapper == null) {
mapper = new ObjectMapper();
// Do not include null values in both serialization and deserialization.
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setPropertyInclusion(JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL));
}
return mapper;
}
private static HttpURLConnection uploadFileToMicrocks(URL microcksApiURL, File file, String contentType) throws IOException {
// Creates a unique boundary based on time stamp
String boundary = "===" + System.currentTimeMillis() + "===";
HttpURLConnection httpConn = (HttpURLConnection) microcksApiURL.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (OutputStream os = httpConn.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8), true);
FileInputStream is = new FileInputStream(file)) {
writer.append("--" + boundary)
.append(HTTP_UPLOAD_LINE_FEED)
.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"")
.append(HTTP_UPLOAD_LINE_FEED)
.append("Content-Type: " + contentType)
.append(HTTP_UPLOAD_LINE_FEED)
.append("Content-Transfer-Encoding: binary")
.append(HTTP_UPLOAD_LINE_FEED)
.append(HTTP_UPLOAD_LINE_FEED);
writer.flush();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.flush();
// Finalize writer with a boundary before flushing.
writer.append(HTTP_UPLOAD_LINE_FEED)
.append("--" + boundary + "--")
.append(HTTP_UPLOAD_LINE_FEED).flush();
}
return httpConn;
}
private static TestResult refreshTestResult(String microcksContainerHttpEndpoint, String testResultId) throws IOException {
// Build a new client on correct API endpoint.
URL url = new URL(microcksContainerHttpEndpoint + "/api/tests/" + testResultId);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("GET");
httpConn.setRequestProperty("Accept", "application/json");
httpConn.setDoOutput(false);
// Send the request and parse response body.
StringBuilder content = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream()))) {
String inputLine;
while ((inputLine = br.readLine()) != null) {
content.append(inputLine);
}
}
// Disconnect Http connection.
httpConn.disconnect();
return getMapper().readValue(content.toString(), TestResult.class);
}
public static class ArtifactLoadException extends RuntimeException {
public ArtifactLoadException(String message) {
super(message);
}
public ArtifactLoadException(String message, Throwable cause) {
super(message, cause);
}
}
public static class SecretCreationException extends RuntimeException {
public SecretCreationException(String message) {
super(message);
}
public SecretCreationException(String message, Throwable cause) {
super(message, cause);
}
}
}