diff --git a/CHANGELOG.md b/CHANGELOG.md index 7267c2b355f..cbf5e91e0b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Fix #3636: ensure proper handling of LogWatch closure wrt its streams #### Improvements +* Fix #3615: opt into bookmarks by default * Fix #3600: add owner references support to HasMetadata #### Dependency Upgrade @@ -23,6 +24,7 @@ * Fix #3593: Add support for Istio extension #### _**Note**_: Breaking changes in the API +* If you do not wish to receive bookmarks, then set ListOptions.allowWatchBookmarks=false - otherwise all Watches will default to requesting bookmarks. If supported by the api-server, bookmarks will avoid 410 exceptions and keep the watch alive longer. If you are using the mock framework with explicit uris, you may need to update your expected watch endpoints to include the parameter allowWatchBookmarks=true * Refactoring #3547: due to an abstraction layer added over okHttp, the following api changes were made: * OperationContext withOkHttpClient was removed, it should be needed to be directly called * PatchType.getMediaType was replaced with PatchType.getContentType diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java index a915909c86a..a237ce4bc66 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java @@ -67,6 +67,8 @@ public abstract class AbstractWatchManager implements Wat private URL requestUrl; private final AtomicBoolean reconnectPending = new AtomicBoolean(false); + + private final boolean receiveBookmarks; AbstractWatchManager( Watcher watcher, BaseOperation baseOperation, ListOptions listOptions, int reconnectLimit, int reconnectInterval, int maxIntervalExponent, Supplier clientSupplier @@ -77,6 +79,11 @@ public abstract class AbstractWatchManager implements Wat this.resourceVersion = new AtomicReference<>(listOptions.getResourceVersion()); this.currentReconnectAttempt = new AtomicInteger(0); this.forceClosed = new AtomicBoolean(); + this.receiveBookmarks = Boolean.TRUE.equals(listOptions.getAllowWatchBookmarks()); + // opt into bookmarks by default + if (listOptions.getAllowWatchBookmarks() == null) { + listOptions.setAllowWatchBookmarks(true); + } this.baseOperation = baseOperation; this.requestUrl = baseOperation.getNamespacedUrl(); this.listOptions = listOptions; @@ -184,6 +191,10 @@ boolean isForceClosed() { } void eventReceived(Watcher.Action action, HasMetadata resource) { + if (!receiveBookmarks && action == Action.BOOKMARK) { + // the user didn't ask for bookmarks, just filter them + return; + } // the WatchEvent deserialization is not specifically typed // modify the type here if needed if (resource != null && !baseOperation.getType().isAssignableFrom(resource.getClass())) { diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/RawCustomResourceOperationsImplTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/RawCustomResourceOperationsImplTest.java index 634de087430..e231074183d 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/RawCustomResourceOperationsImplTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/RawCustomResourceOperationsImplTest.java @@ -827,7 +827,7 @@ public void onClose(WatcherException cause) { // Then assertThat(eventReceived).hasValue("{\"kind\":\"Hello\",\"metadata\":{\"name\":\"test\"}}"); assertThat(result).isNotNull(); - verify(builder, Mockito.times(1)).uri(URI.create("https://localhost:8443/apis/test.fabric8.io/v1alpha1/hellos?watch=true")); + verify(builder, Mockito.times(1)).uri(URI.create("https://localhost:8443/apis/test.fabric8.io/v1alpha1/hellos?allowWatchBookmarks=true&watch=true")); } private void mockCallWithResponse(int code) throws IOException { diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceTest.java index eedcf32c142..c33a1e60550 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceTest.java @@ -312,7 +312,7 @@ void testStatusUpdate() throws IOException { @DisplayName("Should be able to watch some resource in a namespace with null name, labelSelector and ListOptions") void testWatchAllResource() throws IOException, InterruptedException { // Given - server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?watch=true") + server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_PERIOD) @@ -340,7 +340,7 @@ public void onClose(WatcherException cause) { } @DisplayName("Should be able to watch some resource in a namespace") void testWatchAllResourceInNamespace() throws IOException, InterruptedException { // Given - server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?watch=true") + server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_PERIOD) @@ -369,7 +369,7 @@ public void onClose(WatcherException cause) { } @DisplayName("Should be able to watch a single resource with some name") void testWatchSingleResource() throws IOException, InterruptedException { // Given - server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos"+ "?fieldSelector=" + Utils.toUrlEncoded("metadata.name=example-hello")+"&watch=true") + server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos"+ "?fieldSelector=" + Utils.toUrlEncoded("metadata.name=example-hello")+"&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_PERIOD) @@ -397,7 +397,7 @@ public void onClose(WatcherException cause) { } @DisplayName("Should be able to watch with labelSelectors") void testWatchWithLabels() throws IOException, InterruptedException { // Given - server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?labelSelector="+ Utils.toUrlEncoded("foo=bar")+ "&watch=true") + server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?labelSelector="+ Utils.toUrlEncoded("foo=bar")+ "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_PERIOD) @@ -426,7 +426,7 @@ public void onClose(WatcherException cause) { } void testWatchSomeResourceVersion() throws IOException, InterruptedException { // Given String watchResourceVersion = "1001"; - server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?resourceVersion=" + watchResourceVersion + "&watch=true") + server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?resourceVersion=" + watchResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_PERIOD) @@ -456,7 +456,7 @@ public void onClose(WatcherException cause) { } void testWatchNamespaceAndSomeResourceVersion() throws IOException, InterruptedException { // Given String watchResourceVersion = "1001"; - server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?resourceVersion=" + watchResourceVersion + "&watch=true") + server.expect().withPath("/apis/test.fabric8.io/v1alpha1/namespaces/ns1/hellos?resourceVersion=" + watchResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_PERIOD) diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java index 16de2bd079a..ba5eea720d2 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java @@ -117,7 +117,7 @@ void testNamespacedPodInformer() throws InterruptedException { server.expect().withPath("/api/v1/namespaces/test/pods") .andReturn(200, getList(startResourceVersion, Pod.class)).once(); - server.expect().withPath("/api/v1/namespaces/test/pods?resourceVersion=" + startResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/namespaces/test/pods?resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -160,7 +160,7 @@ void testInformerWithNamespaceAndNameConfigured() throws InterruptedException { server.expect().withPath("/api/v1/namespaces/test/pods?fieldSelector=" + Utils.toUrlEncoded("metadata.name=pod1")) .andReturn(200, getList(startResourceVersion, Pod.class)).once(); - server.expect().withPath("/api/v1/namespaces/test/pods?fieldSelector=" + Utils.toUrlEncoded("metadata.name=pod1") + "&resourceVersion=" + startResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/namespaces/test/pods?fieldSelector=" + Utils.toUrlEncoded("metadata.name=pod1") + "&resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -204,7 +204,7 @@ void testAllNamespacedInformer() throws InterruptedException { server.expect().withPath("/api/v1/pods") .andReturn(200, new PodListBuilder().withNewMetadata().withResourceVersion(startResourceVersion).endMetadata().withItems(Collections.emptyList()).build()).once(); - server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -248,7 +248,7 @@ void shouldReconnectInCaseOf410() throws InterruptedException { server.expect().withPath("/api/v1/pods") .andReturn(200, new PodListBuilder().withNewMetadata().withResourceVersion(startResourceVersion).endMetadata().withItems(Collections.emptyList()).build()).once(); - server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -259,7 +259,7 @@ void shouldReconnectInCaseOf410() throws InterruptedException { server.expect().withPath("/api/v1/pods") .andReturn(200, new PodListBuilder().withNewMetadata().withResourceVersion(mid2ResourceVersion).endMetadata().withItems( new PodBuilder().withNewMetadata().withNamespace("test").withName("pod1").withResourceVersion(endResourceVersion).endMetadata().build()).build()).times(2); - server.expect().withPath("/api/v1/pods?resourceVersion=" + mid2ResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/pods?resourceVersion=" + mid2ResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -302,7 +302,7 @@ void shouldDeleteIfMissingOnResync() throws InterruptedException { server.expect().withPath("/api/v1/pods") .andReturn(200, new PodListBuilder().withNewMetadata().withResourceVersion(startResourceVersion).endMetadata().withItems(Collections.emptyList()).build()).once(); - server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -348,7 +348,7 @@ void testHasSynced() { String startResourceVersion = "1000", endResourceVersion = "1001"; server.expect().withPath("/api/v1/namespaces/test/pods") .andReturn(200, new PodListBuilder().withNewMetadata().withResourceVersion(startResourceVersion).endMetadata().withItems(Collections.emptyList()).build()).once(); - server.expect().withPath("/api/v1/namespaces/test/pods?resourceVersion=" + startResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/namespaces/test/pods?resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -834,7 +834,7 @@ void testReconnectAfterOnCloseException() throws InterruptedException { .andReturn(200, new PodListBuilder().withNewMetadata().withResourceVersion(startResourceVersion).endMetadata().withItems(Collections.emptyList()).build()).once(); // initial watch - terminates with an exception - server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/pods?resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -844,7 +844,7 @@ void testReconnectAfterOnCloseException() throws InterruptedException { .done().always(); // should pick this up after the termination - server.expect().withPath("/api/v1/pods?resourceVersion=" + midResourceVersion + "&watch=true") + server.expect().withPath("/api/v1/pods?resourceVersion=" + midResourceVersion + "&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(WATCH_EVENT_EMIT_TIME) @@ -991,7 +991,7 @@ private void setupMockServerExpectationsWithVersion(Clas watchUrl += "?"; } - watchUrl += "resourceVersion=" + startResourceVersion + "&watch=true"; + watchUrl += "resourceVersion=" + startResourceVersion + "&allowWatchBookmarks=true&watch=true"; server.expect().withPath(watchUrl) .andUpgradeToWebSocket() .open() diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/EventTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/EventTest.java index 491c70fae8c..ed09386f1e4 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/EventTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/EventTest.java @@ -56,7 +56,7 @@ void watch() throws InterruptedException { .build(); server.expect() - .withPath("/api/v1/namespaces/ns1/events?watch=true") + .withPath("/api/v1/namespaces/ns1/events?allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open().waitFor(50) .andEmit(new WatchEvent(testEvent, "ADDED")) .done().once(); diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/InformTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/InformTest.java index 0e8d1606810..cde01b87386 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/InformTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/InformTest.java @@ -61,7 +61,7 @@ void testInformPodWithLabel() throws InterruptedException { .once(); server.expect() - .withPath("/api/v1/namespaces/test/pods?labelSelector=my-label&resourceVersion=1&watch=true") + .withPath("/api/v1/namespaces/test/pods?labelSelector=my-label&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(EVENT_WAIT_PERIOD_MS) @@ -114,7 +114,7 @@ void testInformGeneric() throws InterruptedException { .once(); server.expect() - .withPath("/apis/demos.fabric8.io/v1/namespaces/test/dummies?labelSelector=my-label&resourceVersion=1&watch=true") + .withPath("/apis/demos.fabric8.io/v1/namespaces/test/dummies?labelSelector=my-label&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(EVENT_WAIT_PERIOD_MS) @@ -176,7 +176,7 @@ void testGenericWithKnownType() throws InterruptedException { .once(); server.expect() - .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true") + .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(EVENT_WAIT_PERIOD_MS) @@ -235,7 +235,7 @@ void testRunnableInformer() throws InterruptedException { .once(); server.expect() - .withPath("/api/v1/namespaces/test/pods?labelSelector=my-label&resourceVersion=1&watch=true") + .withPath("/api/v1/namespaces/test/pods?labelSelector=my-label&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(EVENT_WAIT_PERIOD_MS) diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/PodTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/PodTest.java index 23fa7576f14..c46c7943329 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/PodTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/PodTest.java @@ -362,7 +362,7 @@ void testWatch() throws InterruptedException { .addToItems(pod1) .build() ).once(); - server.expect().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&watch=true") + server.expect().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(50).andEmit(new WatchEvent(pod1, "DELETED")) @@ -436,7 +436,7 @@ void testWait() throws InterruptedException { server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1").andReturn(200, notReady).once(); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(50).andEmit(new WatchEvent(ready, "MODIFIED")) .done() diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceListTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceListTest.java index 751aa9de2c5..d08a8041c6a 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceListTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceListTest.java @@ -188,13 +188,13 @@ void testSuccessfulWaitUntilCondition() throws InterruptedException { ResourceTest.list(server, noReady1); ResourceTest.list(server, noReady2); - server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(ready1, "MODIFIED")) .done() .once(); - server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod2&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod2&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(ready2, "MODIFIED")) .done() @@ -234,7 +234,7 @@ void testPartialSuccessfulWaitUntilCondition() { .build(); // This pod has a non-retryable error. - server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true") + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(gone, "ERROR")) @@ -242,7 +242,7 @@ void testPartialSuccessfulWaitUntilCondition() { .once(); // This pod succeeds. - server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod2&resourceVersion=1&watch=true") + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod2&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(ready2, "MODIFIED")) @@ -284,14 +284,14 @@ void testAllFailedWaitUntilCondition() { .build(); // Both pods have a non-retryable error. - server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true") + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(gone, "ERROR")) .done() .once(); - server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod2&resourceVersion=1&watch=true") + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?fieldSelector=metadata.name%3Dpod2&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(gone, "ERROR")) diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceTest.java index 4b23a331058..6e69a2abebc 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ResourceTest.java @@ -211,7 +211,7 @@ void testWatch() throws InterruptedException { server.expect().get().withPath("/api/v1/namespaces/test/pods").andReturn(200, pod1).once(); server.expect().post().withPath("/api/v1/namespaces/test/pods").andReturn(201, pod1).once(); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(1000).andEmit(new WatchEvent(pod1, "DELETED")) .done() @@ -247,7 +247,7 @@ void testWaitUntilReady() throws InterruptedException { list(noReady); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(ready, "MODIFIED")) .done() @@ -284,7 +284,7 @@ void testWaitUntilExistsThenReady() throws InterruptedException { // and again so that "periodicWatchUntilReady" successfully begins server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1").andReturn(200, noReady).times(2); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(100).andEmit(new WatchEvent(ready, "MODIFIED")) .done() @@ -332,7 +332,7 @@ void testWaitUntilCondition() throws InterruptedException { // at first the pod is non-ready list(noReady); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(1000).andEmit(new WatchEvent(ready, "MODIFIED")) .waitFor(2000).andEmit(new WatchEvent(withConditionBeingFalse, "MODIFIED")) @@ -370,7 +370,7 @@ void tesErrorEventDuringWaitReturnFromAPIIfMatch() throws InterruptedException { // once not ready, to begin watch list(noReady); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(status, "ERROR")) .waitFor(500).andEmit(new WatchEvent(ready, "MODIFIED")) @@ -398,13 +398,13 @@ void testRetryOnErrorEventDuringWait() throws InterruptedException { // once not ready, to begin watch list(noReady); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(status, "ERROR")) .done() .once(); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(ready, "MODIFIED")) .done() @@ -449,7 +449,7 @@ void testRetryWatchOnHttpGone() throws InterruptedException { // once not ready, to begin watch list(noReady); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(500).andEmit(new WatchEvent(status, "ERROR")) .done() @@ -475,7 +475,7 @@ void testWaitOnConditionDeleted() throws InterruptedException { list(ready); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(1000).andEmit(new WatchEvent(ready, "DELETED")) .done() @@ -499,7 +499,7 @@ void testCreateAndWaitUntilReady() throws InterruptedException { list(noReady); server.expect().post().withPath("/api/v1/namespaces/test/pods").andReturn(201, noReady).once(); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true").andUpgradeToWebSocket() + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true").andUpgradeToWebSocket() .open() .waitFor(1000).andEmit(new WatchEvent(ready, "MODIFIED")) .done() @@ -543,7 +543,7 @@ void testFromServerWaitUntilConditionAlwaysGetsResourceFromServer() throws Excep .endMetadata() .build(); list(conditionNotMetPod); - server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod&resourceVersion=1&watch=true") + server.expect().get().withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open() .immediately().andEmit(new WatchEvent(conditionNotMetPod, "MODIFIED")) .waitFor(10).andEmit(new WatchEvent(conditionMetPod, "MODIFIED")) diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/WatchTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/WatchTest.java index 069c7e58513..1aaeaaf1425 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/WatchTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/WatchTest.java @@ -39,8 +39,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static io.fabric8.kubernetes.client.Watcher.Action.DELETED; import static io.fabric8.kubernetes.client.Watcher.Action.BOOKMARK; +import static io.fabric8.kubernetes.client.Watcher.Action.DELETED; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -67,7 +67,7 @@ void setUp() { void testTryWithResourcesConnectsThenReceivesEvent() throws InterruptedException { // Given server.expect() - .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true") + .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open() .waitFor(EVENT_WAIT_PERIOD_MS).andEmit(new WatchEvent(pod1, "DELETED")) .waitFor(EVENT_WAIT_PERIOD_MS).andEmit(outdatedEvent()).done().once(); @@ -103,7 +103,7 @@ void testTryWithResourcesCantConnectShouldCloseAndThenThrowException() throws Ex // Given final CountDownLatch closeLatch = new CountDownLatch(1); server.expect() - .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true") + .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andReturn(410, outdatedEvent()).once(); final Watcher watcher = new Watcher() { @Override @@ -138,7 +138,7 @@ public void onClose() { void testWithTimeoutSecondsShouldAddQueryParam() throws InterruptedException { // Given server.expect() - .withPath("/api/v1/namespaces/test/pods?timeoutSeconds=30&watch=true") + .withPath("/api/v1/namespaces/test/pods?timeoutSeconds=30&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open() .waitFor(EVENT_WAIT_PERIOD_MS).andEmit(new WatchEvent(pod1, "DELETED")) .waitFor(EVENT_WAIT_PERIOD_MS).andEmit(outdatedEvent()).done().once(); @@ -166,7 +166,7 @@ public void onClose(WatcherException cause) { } void testHttpErrorReconnect() throws InterruptedException { // Given client.getConfiguration().setWatchReconnectInterval(10); - final String path = "/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true"; + final String path = "/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true"; // accept watch and disconnect server.expect().withPath(path).andUpgradeToWebSocket().open().done().once(); // refuse reconnect attempts 6 times @@ -200,7 +200,7 @@ void testOnCloseEvent() throws InterruptedException { final CountDownLatch closeLatch = new CountDownLatch(1); server.expect() - .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true") + .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open().waitFor(EVENT_WAIT_PERIOD_MS).andEmit(new WatchEvent(pod1, "MODIFIED")).waitFor(EVENT_WAIT_PERIOD_MS) .andEmit(new WatchEvent(pod1, "MODIFIED")).done().once(); @@ -237,7 +237,7 @@ void testReconnectsWithLastResourceVersion() throws InterruptedException { final Pod pod1update = new PodBuilder().withNewMetadata().withNamespace("test").withName("pod1") .withResourceVersion("10").endMetadata().build(); - final String path = "/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true"; + final String path = "/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true"; server.expect() .withPath(path) @@ -246,7 +246,7 @@ void testReconnectsWithLastResourceVersion() throws InterruptedException { .waitFor(EVENT_WAIT_PERIOD_MS).andEmit(new WatchEvent(pod1update, "MODIFIED")) .done().once(); - final String reconnectPath = "/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=10&watch=true"; + final String reconnectPath = "/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=10&allowWatchBookmarks=true&watch=true"; server.expect() .withPath(reconnectPath) @@ -284,7 +284,7 @@ private static WatchEvent outdatedEvent() { void testTryWithResourcesConnectsThenReceivesEventBookmark() throws InterruptedException { // Given server.expect() - .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&watch=true") + .withPath("/api/v1/namespaces/test/pods?fieldSelector=metadata.name%3Dpod1&resourceVersion=1&allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open() .waitFor(EVENT_WAIT_PERIOD_MS).andEmit(new WatchEvent(pod1, "BOOKMARK")) .waitFor(EVENT_WAIT_PERIOD_MS).andEmit(outdatedEvent()).done().once(); @@ -306,7 +306,7 @@ public void onClose(WatcherException cause) { } }; // When - try (Watch watch = client.pods().withName("pod1").withResourceVersion("1").watch(watcher)) { + try (Watch watch = client.pods().withName("pod1").withResourceVersion("1").watch(new ListOptionsBuilder().withAllowWatchBookmarks(true).build(), watcher)) { // Then assertNotNull(watch); assertTrue(bookmarkLatch.await(10, TimeUnit.SECONDS));