Skip to content

Commit 5a216fc

Browse files
authored
feat: user Vert.x as the default HttpClient implementation
Signed-off-by: Marc Nuri <marc@marcnuri.com>
1 parent 279b358 commit 5a216fc

File tree

10 files changed

+142
-75
lines changed

10 files changed

+142
-75
lines changed

.github/workflows/e2e-httpclient-tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
fail-fast: false
4040
matrix:
4141
kubernetes: [v1.28.1,v1.27.5]
42-
httpclient: [jdk,jetty,vertx]
42+
httpclient: [jdk,jetty,okhttp]
4343
steps:
4444
- name: Checkout
4545
uses: actions/checkout@v4

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
* Fix #6158: Removed deprecated methods from `io.fabric8.kubernetes.client.utils.IOHelpers` class
4444
* Fix #6159: Removed deprecated `io.fabric8.kubernetes.client.utils.Utils.getPluralFromKind` method
4545
* Fix #6361: Renamed SettableBeanPropertyDelegate to SettableBeanPropertyDelegating
46+
* Fix #6470: Switched default HTTP client from OkHttp to Vert.x (`kubernetes-httpclient-vertx`)
4647
* Fix #6603: Removed deprecated `io.fabric8.openshift.api.model.runtime.RawExtension` class
4748
* Fix #6605: Removed deprecated `ApiVersionUtil` classes in extension modules
4849
* Fix #6609: Removed deprecated `io.fabric8.crd.generator.CRDInfo.getVersion` method

chaos-tests/pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@
4949
<exclusions>
5050
<exclusion>
5151
<groupId>io.fabric8</groupId>
52-
<artifactId>kubernetes-httpclient-okhttp</artifactId>
52+
<artifactId>kubernetes-httpclient-vertx</artifactId>
5353
</exclusion>
5454
</exclusions>
5555
</dependency>
5656
<dependency>
5757
<groupId>io.fabric8</groupId>
58-
<artifactId>kubernetes-httpclient-okhttp</artifactId>
58+
<artifactId>kubernetes-httpclient-vertx</artifactId>
5959
<scope>test</scope>
6060
</dependency>
6161

doc/FAQ.md

+99-49
Large diffs are not rendered by default.

doc/MIGRATION-v7.md

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Contents
44
- [Java baseline set to Java 11](#java-11)
5+
- [Vert.x as default HttpClient implementation](#vertx-httpclient)
56
- [Bouncy Castle is no longer needed](#bouncy-castle)
67
- [Config changes](#config-changes)
78
- [Support for multiple kubeconfig files](#config-changes-multiple-kubeconfig)
@@ -41,6 +42,14 @@ Starting from version 7.0.0, you will need a Java 11+ runtime (using the latest
4142
It's been more than 10 years since Java 8 was released, and it's no longer supported by most vendors.
4243
We made our best effort to keep the client compatible with Java 8 for as long as possible, but it's time to move on.
4344

45+
## Vert.x as default HttpClient implementation <a href="#vertx-httpclient" id="vertx-httpclient"/>
46+
47+
OkHttp has been replaced by Vert.x as the default HttpClient implementation.
48+
As of version 7.0.0, the Fabric8 Kubernetes Client `io.fabric8:kubernetes-client` and `io.fabric8:openshift-client` include a transitive dependency to the `io.fabric8:kubernetes-httpclient-vertx` module.
49+
50+
If you want to continue using OkHttp as the HttpClient, you can do so by adding the `io.fabric8:kubernetes-httpclient-okhttp` module as a dependency.
51+
It is also recommended (although not mandatory) to add an exclusion for the `io.fabric8:kubernetes-httpclient-vertx` module to avoid having both implementations in the classpath.
52+
4453
## Bouncy Castle is no longer needed <a href="#bouncy-castle" id="bouncy-castle"/>
4554

4655
The Bouncy Castle library is no longer needed as a dependency.

kubernetes-client/pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
</dependency>
6868
<dependency>
6969
<groupId>io.fabric8</groupId>
70-
<artifactId>kubernetes-httpclient-okhttp</artifactId>
70+
<artifactId>kubernetes-httpclient-vertx</artifactId>
7171
<scope>runtime</scope>
7272
</dependency>
7373

@@ -205,7 +205,7 @@
205205
</goals>
206206
<configuration>
207207
<excludeDependencies>
208-
kubernetes-httpclient-okhttp
208+
kubernetes-httpclient-vertx
209209
</excludeDependencies>
210210
<instructions>
211211
<Bundle-Name>${project.name}</Bundle-Name>

kubernetes-itests/pom.xml

+5-5
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
<exclusions>
103103
<exclusion>
104104
<groupId>io.fabric8</groupId>
105-
<artifactId>kubernetes-httpclient-okhttp</artifactId>
105+
<artifactId>kubernetes-httpclient-vertx</artifactId>
106106
</exclusion>
107107
</exclusions>
108108
</dependency>
@@ -122,7 +122,7 @@
122122
<exclusions>
123123
<exclusion>
124124
<groupId>io.fabric8</groupId>
125-
<artifactId>kubernetes-httpclient-okhttp</artifactId>
125+
<artifactId>kubernetes-httpclient-vertx</artifactId>
126126
</exclusion>
127127
</exclusions>
128128
</dependency>
@@ -133,7 +133,7 @@
133133
</dependencies>
134134
</profile>
135135
<profile>
136-
<id>httpclient-vertx</id>
136+
<id>httpclient-okhttp</id>
137137
<dependencies>
138138
<dependency>
139139
<groupId>io.fabric8</groupId>
@@ -142,13 +142,13 @@
142142
<exclusions>
143143
<exclusion>
144144
<groupId>io.fabric8</groupId>
145-
<artifactId>kubernetes-httpclient-okhttp</artifactId>
145+
<artifactId>kubernetes-httpclient-vertx</artifactId>
146146
</exclusion>
147147
</exclusions>
148148
</dependency>
149149
<dependency>
150150
<groupId>io.fabric8</groupId>
151-
<artifactId>kubernetes-httpclient-vertx</artifactId>
151+
<artifactId>kubernetes-httpclient-okhttp</artifactId>
152152
</dependency>
153153
</dependencies>
154154
</profile>

kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java

+9-11
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import java.util.function.Function;
7575

7676
import static org.assertj.core.api.Assertions.assertThat;
77+
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
7778
import static org.awaitility.Awaitility.await;
7879
import static org.junit.jupiter.api.Assertions.assertEquals;
7980
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -103,7 +104,7 @@ class DefaultSharedIndexInformerTest {
103104
.withKind("Animal")
104105
.withScope("Namespaced")
105106
.build();
106-
private KubernetesClient client;
107+
KubernetesClient client;
107108
private SharedInformerFactory factory;
108109

109110
@BeforeEach
@@ -212,7 +213,7 @@ void testInformerWithNamespaceAndNameConfigured() throws InterruptedException {
212213
RESYNC_PERIOD);
213214
CountDownLatch foundExistingPod = new CountDownLatch(1);
214215
podInformer.addEventHandler(
215-
new ResourceEventHandler<Pod>() {
216+
new ResourceEventHandler<>() {
216217
@Override
217218
public void onAdd(Pod obj) {
218219
if (obj.getMetadata().getName().equalsIgnoreCase("pod1")) {
@@ -541,7 +542,7 @@ void testEventListeners() throws InterruptedException {
541542
SharedIndexInformer<Pod> podInformer = factory.sharedIndexInformerFor(Pod.class, 1000L);
542543
CountDownLatch failureCallbackReceived = new CountDownLatch(1);
543544
podInformer.addEventHandler(
544-
new ResourceEventHandler<Pod>() {
545+
new ResourceEventHandler<>() {
545546
@Override
546547
public void onAdd(Pod obj) {
547548
}
@@ -1224,22 +1225,19 @@ void testClientStopClosesInformer() throws InterruptedException {
12241225
}
12251226

12261227
@Test
1227-
void testClientStopClosesInformerBeforeStarting() throws InterruptedException {
1228+
void clientStopPreventsInformerFromStarting() {
12281229
// Given
12291230
setupMockServerExpectations(Animal.class, "ns1", this::getList,
12301231
r -> new WatchEvent(getAnimal("red-panda", "Carnivora", r), "ADDED"), null, null);
1231-
1232-
// When
12331232
SharedIndexInformer<GenericKubernetesResource> animalSharedIndexInformer = client
12341233
.genericKubernetesResources(animalContext)
12351234
.inNamespace("ns1")
12361235
.runnableInformer(60 * WATCH_EVENT_EMIT_TIME);
1237-
12381236
client.close();
1239-
1240-
animalSharedIndexInformer.start();
1241-
1242-
assertTrue(animalSharedIndexInformer.stopped().toCompletableFuture().isDone());
1237+
// When
1238+
assertThatIllegalStateException()
1239+
.isThrownBy(animalSharedIndexInformer::start)
1240+
.withMessage("Client is closed");
12431241
}
12441242

12451243
private KubernetesResource getAnimal(String name, String order, String resourceVersion) {

kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/PodTest.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import io.fabric8.kubernetes.client.utils.InputStreamPumper;
4747
import io.fabric8.kubernetes.client.utils.Utils;
4848
import io.fabric8.mockwebserver.internal.WebSocketMessage;
49-
import okio.ByteString;
5049
import org.awaitility.Awaitility;
5150
import org.junit.jupiter.api.BeforeEach;
5251
import org.junit.jupiter.api.Test;
@@ -830,7 +829,7 @@ void testPortForward() throws IOException {
830829
} while (read >= 0);
831830
buffer.flip();
832831
channel.socket().close();
833-
assertEquals("Hello World", ByteString.of(buffer).utf8());
832+
assertEquals("Hello World", StandardCharsets.UTF_8.decode(buffer).toString());
834833
assertFalse(portForward.errorOccurred());
835834
assertEquals(0, portForward.getClientThrowables().size());
836835
assertEquals(0, portForward.getServerThrowables().size());

log4j/src/main/java/io/fabric8/kubernetes/log4j/lookup/KubernetesLookup.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ public class KubernetesLookup extends AbstractLookup {
166166
.isClassAvailable("org.apache.logging.log4j.spring.cloud.config.client.SpringEnvironmentHolder")
167167
|| LoaderUtil.isClassAvailable("org.apache.logging.log4j.spring.boot.SpringEnvironmentHolder");
168168

169+
// Vert.x uses Log4j as a logger, if the KubernetesLookup info is initialized when the plugin is instantiated
170+
// it will cause an infinite loop since the Log4j factory will invoke the KubernetesLookup plugin,
171+
// the Vert.x client will invoke the Log4j factory again, and so forth.
172+
private volatile boolean initialized;
169173
private Pod pod;
170174
private Namespace namespace;
171175
private URL masterUrl;
@@ -177,14 +181,14 @@ public KubernetesLookup() {
177181
this.pod = null;
178182
this.namespace = null;
179183
this.masterUrl = null;
180-
initialize(this);
184+
this.initialized = false;
181185
}
182186

183187
KubernetesLookup(Pod pod, Namespace namespace, URL masterUrl) {
184188
this.pod = pod;
185189
this.namespace = namespace;
186190
this.masterUrl = masterUrl;
187-
initialize(this);
191+
this.initialized = false;
188192
}
189193

190194
private static void initialize(KubernetesLookup lookup) {
@@ -252,7 +256,7 @@ private static void tryInitializeFields(KubernetesLookup lookup) {
252256
* <p>
253257
* Used in tests to provide a mock client.
254258
* </p>
255-
*
259+
*
256260
* @return A Kubernetes client.
257261
*/
258262
protected KubernetesClient createClient() {
@@ -370,6 +374,12 @@ private static Container getContainer(PodSpec podSpec, String containerName) {
370374

371375
@Override
372376
public String lookup(final LogEvent event, final String key) {
377+
synchronized (this) {
378+
if (!initialized) {
379+
initialize(this);
380+
initialized = true;
381+
}
382+
}
373383
KubernetesInfo info;
374384
READ_LOCK.lock();
375385
try {

0 commit comments

Comments
 (0)