diff --git a/CHANGELOG.md b/CHANGELOG.md index 7842c79f3c..7c31475043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,9 @@ Usage: ./scripts/extract-changelog-for-version.sh 1.3.37 5 ``` ### 1.0.2-SNAPSHOT -* Fix: Added quickstart for Micronaut framework +* Fix 429: Added quickstart for Micronaut framework +* Fix 440: Added quickstart for MicroProfile running on OpenLiberty +* Fix: Valid content type for REST docker API requests with body ### 1.0.1 (2020-10-05) * Fix #381: Remove root as default user in AssemblyConfigurationUtils#getAssemblyConfigurationOrCreateDefault diff --git a/jkube-kit/build/service/docker/pom.xml b/jkube-kit/build/service/docker/pom.xml index e5081cc7d1..033d13dca3 100644 --- a/jkube-kit/build/service/docker/pom.xml +++ b/jkube-kit/build/service/docker/pom.xml @@ -68,6 +68,10 @@ org.jmockit jmockit + + org.assertj + assertj-core + org.hamcrest hamcrest-all diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/ApacheHttpClientDelegate.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/ApacheHttpClientDelegate.java index f5b4576928..f1d2a83714 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/ApacheHttpClientDelegate.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/ApacheHttpClientDelegate.java @@ -15,6 +15,7 @@ import java.io.File; import java.io.IOException; +import java.net.URLConnection; import java.nio.charset.Charset; import java.util.Map; import java.util.Map.Entry; @@ -68,8 +69,7 @@ public int delete(String url, int... statusCodes) throws IOException { public static class StatusCodeResponseHandler implements ResponseHandler { @Override - public Integer handleResponse(HttpResponse response) - throws IOException { + public Integer handleResponse(HttpResponse response) { return response.getStatusLine().getStatusCode(); } @@ -134,31 +134,35 @@ public int put(String url, Object body, int... statusCodes) throws IOException { // ========================================================================================= - private HttpUriRequest addDefaultHeaders(HttpUriRequest req) { + private HttpUriRequest addDefaultHeaders(HttpUriRequest req, Object body) { req.addHeader(HttpHeaders.ACCEPT, "*/*"); - req.addHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + if (body instanceof File) { + req.addHeader(HttpHeaders.CONTENT_TYPE, URLConnection.guessContentTypeFromName(((File)body).getName())); + } + if (body != null && !req.containsHeader(HttpHeaders.CONTENT_TYPE)) { + req.addHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + } return req; } - private HttpUriRequest newDelete(String url) { - return addDefaultHeaders(new HttpDelete(url)); + return addDefaultHeaders(new HttpDelete(url), null); } private HttpUriRequest newGet(String url) { - return addDefaultHeaders(new HttpGet(url)); + return addDefaultHeaders(new HttpGet(url), null); } private HttpUriRequest newPut(String url, Object body) { HttpPut put = new HttpPut(url); setEntityIfGiven(put, body); - return addDefaultHeaders(put); + return addDefaultHeaders(put, body); } private HttpUriRequest newPost(String url, Object body) { HttpPost post = new HttpPost(url); setEntityIfGiven(post, body); - return addDefaultHeaders(post); + return addDefaultHeaders(post, body); } diff --git a/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/access/hc/ApacheHttpClientDelegateTest.java b/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/access/hc/ApacheHttpClientDelegateTest.java new file mode 100644 index 0000000000..ff9ea17c13 --- /dev/null +++ b/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/access/hc/ApacheHttpClientDelegateTest.java @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2019 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at: + * + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.jkube.kit.build.service.docker.access.hc; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.function.BiConsumer; + +import org.eclipse.jkube.kit.build.service.docker.access.hc.util.ClientBuilder; + +import mockit.Expectations; +import mockit.Mocked; +import mockit.Verifications; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.assertj.core.groups.Tuple; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@SuppressWarnings({"rawtypes", "unused"}) +public class ApacheHttpClientDelegateTest { + + @Mocked + private ClientBuilder clientBuilder; + @Mocked + private CloseableHttpClient httpClient; + + private ApacheHttpClientDelegate apacheHttpClientDelegate; + + @Before + public void setUp() throws Exception { + // @formatter:off + new Expectations() {{ + clientBuilder.buildBasicClient(); result = httpClient; + }}; + // @formatter:on + apacheHttpClientDelegate = new ApacheHttpClientDelegate(clientBuilder, false); + } + + @Test + public void createBasicClient() { + final CloseableHttpClient result = apacheHttpClientDelegate.createBasicClient(); + assertThat(result).isNotNull(); + } + + @Test + public void delete() throws IOException { + // Given + // @formatter:off + new Expectations() {{ + httpClient.execute((HttpUriRequest) any, (ResponseHandler) any); result = 1337; + }}; + // @formatter:on + // When + final int result = apacheHttpClientDelegate.delete("http://example.com"); + // Then + assertThat(result).isEqualTo(1337); + verifyHttpClientExecute((request, responseHandler) -> + assertThat(request.getAllHeaders()) + .hasSize(1) + .extracting("name", "value") + .containsOnly(new Tuple("Accept", "*/*")) + ); + } + + @Test + public void get() throws IOException { + // Given + // @formatter:off + new Expectations() {{ + httpClient.execute((HttpUriRequest) any, (ResponseHandler) any); result = "Response"; + }}; + // @formatter:on + // When + final String response = apacheHttpClientDelegate.get("http://example.com"); + // Then + assertThat(response).isEqualTo("Response"); + verifyHttpClientExecute((request, responseHandler) ->{ + assertThat(request.getAllHeaders()) + .hasSize(1) + .extracting("name", "value") + .containsOnly(new Tuple("Accept", "*/*")); + assertThat(responseHandler) + .extracting("delegate") + .hasSize(1) + .hasOnlyElementsOfType(ApacheHttpClientDelegate.BodyResponseHandler.class); + }); + } + + @Test + public void postWithStringBody() throws IOException { + // Given + // @formatter:off + new Expectations() {{ + httpClient.execute((HttpUriRequest) any, (ResponseHandler) any); result = "Response"; + }}; + // @formatter:on + // When + final String response = apacheHttpClientDelegate.post( + "http://example.com", "{body}", Collections.singletonMap("EXTRA", "HEADER"), null); + // Then + assertThat(response).isEqualTo("Response"); + verifyHttpClientExecute((request, responseHandler) -> + assertThat(request.getAllHeaders()) + .hasSize(3) + .extracting("name", "value") + .containsOnly( + new Tuple("Accept", "*/*"), + new Tuple("Content-Type", "application/json"), + new Tuple("EXTRA", "HEADER")) + ); + } + + @Test + public void postWithFileBody() throws IOException { + // Given + // @formatter:off + new Expectations() {{ + httpClient.execute((HttpUriRequest) any, (ResponseHandler) any); result = "Response"; + }}; + // @formatter:on + // When + final String response = apacheHttpClientDelegate.post( + "http://example.com", new File("fake-file.tar"), null); + // Then + assertThat(response).isEqualTo("Response"); + verifyHttpClientExecute((request, responseHandler) -> + assertThat(request.getAllHeaders()) + .hasSize(2) + .extracting("name", "value") + .containsOnly( + new Tuple("Accept", "*/*"), + new Tuple("Content-Type", "application/x-tar")) + ); + } + + private void verifyHttpClientExecute(BiConsumer consumer) throws IOException { + // @formatter:off + new Verifications() {{ + HttpUriRequest request; + H responseHandler; + httpClient.execute(request = withCapture(), responseHandler = withCapture()); + consumer.accept(request, responseHandler); + }}; + // @formatter:on + } + +} \ No newline at end of file