diff --git a/CHANGELOG.md b/CHANGELOG.md index a370d1c815..fbba790774 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fix #2373: Unable to create a Template on OCP3 * Fix #2316: Cannot load resource from stream without apiVersion * Fix #2389: KubernetesServer does not use value from https in crud mode +* Fix #2306: Make KubernetesServer CRUD mode work with informers #### Improvements * Fix #2331: Fixed documentation for namespaced informer for all custom types implementing `Namespaced` interface diff --git a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesResponseComposer.java b/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesResponseComposer.java index 185af2466f..d84b64e7c3 100644 --- a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesResponseComposer.java +++ b/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesResponseComposer.java @@ -39,7 +39,8 @@ private static String join(String sep, Collection collection) { @Override public String compose(Collection collection) { return String.format( - "{\"apiVersion\":\"v1\",\"kind\":\"List\", \"items\": [%s]}", + "{\"apiVersion\":\"v1\",\"kind\":\"List\", \"items\": [%s], " + + "\"metadata\": {\"resourceVersion\": \"\", \"selfLink\": \"\"}}", join(",", collection)); } } diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CrudInformerTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CrudInformerTest.java new file mode 100644 index 0000000000..14e60ba886 --- /dev/null +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CrudInformerTest.java @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * 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.fabric8.kubernetes.client.mock; + +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.PodBuilder; +import io.fabric8.kubernetes.api.model.PodList; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.ResourceEventHandler; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.informers.SharedInformerFactory; +import io.fabric8.kubernetes.client.server.mock.KubernetesServer; +import org.junit.Rule; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@EnableRuleMigrationSupport +public class CrudInformerTest { + @Rule + public KubernetesServer server = new KubernetesServer(true, true); + + // https://github.com/fabric8io/kubernetes-client/issues/2306 + @Test + void testCrudInformer() throws InterruptedException { + Pod podToCreate = new PodBuilder().withNewMetadata().withName("pod1").endMetadata().build(); + KubernetesClient client = server.getClient(); + SharedInformerFactory factory = client.informers(); + SharedIndexInformer podInformer = factory.sharedIndexInformerFor(Pod.class, PodList.class, 4000); + BlockingQueue events = new LinkedBlockingQueue<>(); + podInformer.addEventHandler( + new ResourceEventHandler() { + @Override + public void onAdd(Pod obj) { + events.add(obj); + } + + @Override + public void onUpdate(Pod oldObj, Pod newObj) { + } + + @Override + public void onDelete(Pod oldObj, boolean deletedFinalStateUnknown) { + } + }); + factory.startAllRegisteredInformers(); + client.pods().create(podToCreate); + Pod readPod = events.poll(5, TimeUnit.SECONDS); + assertNotNull(readPod); + assertEquals(readPod.getMetadata().getName(), podToCreate.getMetadata().getName()); + factory.stopAllRegisteredInformers(); + } +}