|
26 | 26 | import io.fabric8.kubernetes.api.model.Pod; |
27 | 27 | import io.fabric8.kubernetes.api.model.PodBuilder; |
28 | 28 | import io.fabric8.kubernetes.api.model.PodListBuilder; |
| 29 | +import io.fabric8.kubernetes.api.model.Service; |
29 | 30 | import io.fabric8.kubernetes.api.model.Status; |
30 | 31 | import io.fabric8.kubernetes.api.model.StatusBuilder; |
31 | 32 | import io.fabric8.kubernetes.api.model.WatchEvent; |
|
36 | 37 | import io.fabric8.kubernetes.api.model.rbac.ClusterRoleBindingBuilder; |
37 | 38 | import io.fabric8.kubernetes.client.CustomResourceList; |
38 | 39 | import io.fabric8.kubernetes.client.KubernetesClient; |
| 40 | +import io.fabric8.kubernetes.client.KubernetesClientException; |
39 | 41 | import io.fabric8.kubernetes.client.Watcher; |
| 42 | +import io.fabric8.kubernetes.client.WatcherException; |
40 | 43 | import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; |
41 | 44 | import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; |
42 | 45 | import io.fabric8.kubernetes.client.informers.ResourceEventHandler; |
|
65 | 68 | import java.util.concurrent.ExecutionException; |
66 | 69 | import java.util.concurrent.Future; |
67 | 70 | import java.util.concurrent.TimeUnit; |
| 71 | +import java.util.concurrent.TimeoutException; |
68 | 72 | import java.util.function.BiFunction; |
69 | 73 | import java.util.function.Function; |
70 | 74 |
|
@@ -897,6 +901,51 @@ public void onDelete(Pod oldObj, boolean deletedFinalStateUnknown) { |
897 | 901 | assertFalse(podInformer.isRunning()); |
898 | 902 | } |
899 | 903 |
|
| 904 | + @Test |
| 905 | + void testTerminalException() throws InterruptedException, TimeoutException { |
| 906 | + // should be an initial 404 |
| 907 | + SharedIndexInformer<Pod> informer = client.pods().runnableInformer(0); |
| 908 | + try { |
| 909 | + informer.run(); |
| 910 | + } catch (Exception e) { |
| 911 | + } |
| 912 | + try { |
| 913 | + informer.stopped().get(10, TimeUnit.SECONDS); |
| 914 | + } catch (ExecutionException e) { |
| 915 | + assertTrue(e.getCause() instanceof KubernetesClientException); |
| 916 | + } |
| 917 | + |
| 918 | + String startResourceVersion = "1000"; |
| 919 | + |
| 920 | + // initial list |
| 921 | + server.expect().withPath("/api/v1/pods") |
| 922 | + .andReturn(200, new PodListBuilder().withNewMetadata().withResourceVersion(startResourceVersion).endMetadata() |
| 923 | + .withItems(Collections.emptyList()).build()) |
| 924 | + .once(); |
| 925 | + |
| 926 | + // initial watch - terminates with an exception |
| 927 | + server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") |
| 928 | + .andUpgradeToWebSocket() |
| 929 | + .open() |
| 930 | + .waitFor(WATCH_EVENT_EMIT_TIME) |
| 931 | + .andEmit(new WatchEvent(new Service(), "ADDED")) // not a pod |
| 932 | + .waitFor(OUTDATED_WATCH_EVENT_EMIT_TIME) |
| 933 | + .andEmit(outdatedEvent) |
| 934 | + .done().always(); |
| 935 | + |
| 936 | + // When |
| 937 | + informer = client.pods().inAnyNamespace().runnableInformer(0); |
| 938 | + try { |
| 939 | + informer.run(); |
| 940 | + } catch (Exception e) { |
| 941 | + } |
| 942 | + try { |
| 943 | + informer.stopped().get(10, TimeUnit.SECONDS); |
| 944 | + } catch (ExecutionException e) { |
| 945 | + assertTrue(e.getCause() instanceof WatcherException); |
| 946 | + } |
| 947 | + } |
| 948 | + |
900 | 949 | @Test |
901 | 950 | void testRunAfterStop() { |
902 | 951 | // Given |
|
0 commit comments