From 9e105cb52cbdd1d8244daada8f9c411c71702ad2 Mon Sep 17 00:00:00 2001 From: Steven Hawkins Date: Thu, 19 Sep 2024 05:47:40 +0200 Subject: [PATCH 1/6] fix: support for proxy authentication from proxy URL user info closes: #6247 Signed-off-by: Steve Hawkins Signed-off-by: Marc Nuri --- CHANGELOG.md | 6 ++++++ .../kubernetes/client/utils/HttpClientUtils.java | 12 ++++++++++-- .../kubernetes/client/utils/HttpClientUtilsTest.java | 12 ++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30d3e3f39c0..edd8e45908e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## CHANGELOG +### 6.13.4 (2024-09-25) + +#### Bugs +* Fix #6247: Support for proxy authentication from proxy URL user info + + ### 6.13.3 (2024-08-13) #### Bugs diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java index 3022a748fce..d98d71d2ef8 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java @@ -123,12 +123,15 @@ public static Map createA return interceptors; } - public static String basicCredentials(String username, String password) { - String usernameAndPassword = username + ":" + password; + public static String basicCredentials(String usernameAndPassword) { String encoded = Base64.getEncoder().encodeToString(usernameAndPassword.getBytes(StandardCharsets.UTF_8)); return "Basic " + encoded; } + public static String basicCredentials(String username, String password) { + return basicCredentials(username + ":" + password); + } + /** * @deprecated you should not need to call this method directly. Please create your own HttpClient.Factory * should you need to customize your clients. @@ -229,6 +232,11 @@ static void configureProxy(Config config, HttpClient.Builder builder) builder.proxyAuthorization(basicCredentials(config.getProxyUsername(), config.getProxyPassword())); } + String userInfo = proxyUri.getUserInfo(); + if (userInfo != null) { + builder.proxyAuthorization(basicCredentials(userInfo)); + } + builder.proxyType(toProxyType(proxyUri.getScheme())); } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/HttpClientUtilsTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/HttpClientUtilsTest.java index 25cfcaed57e..208c8c39267 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/HttpClientUtilsTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/HttpClientUtilsTest.java @@ -90,6 +90,18 @@ void testConfigureSocksProxy() throws Exception { Mockito.verify(builder).proxyAddress(new InetSocketAddress("192.168.0.1", 8080)); } + @Test + void testConfigureProxyAuth() throws Exception { + Config config = new ConfigBuilder().withMasterUrl("http://localhost").withHttpProxy("http://user:password@192.168.0.1:8080") + .build(); + Builder builder = Mockito.mock(HttpClient.Builder.class, Mockito.RETURNS_SELF); + + HttpClientUtils.configureProxy(config, builder); + + Mockito.verify(builder).proxyType(HttpClient.ProxyType.HTTP); + Mockito.verify(builder).proxyAuthorization("Basic dXNlcjpwYXNzd29yZA=="); + } + @Test void testCreateApplicableInterceptors() { // Given From 928d356f8eeea95e17632ed76700c65ad4135216 Mon Sep 17 00:00:00 2001 From: fxshlein Date: Mon, 23 Sep 2024 08:29:53 +0200 Subject: [PATCH 2/6] fix(model): use SettableBeanProperty.Delegating for jackson delegation (6343) fix(model): Use SettableBeanProperty.Delegating for jackson delegation Changes the delegation in SettableBeanPropertyDelegate from a custom implementation to the standard way of implementing a delegating property in jackson. This way, if some jackson module overrides methods that are not delegated explicitely here, they will continue to work. Fixes: fabric8io/kubernetes-client#6342 --- fix: SettableBeanProperty.deserializeSetAndReturn should return instance instead of null Signed-off-by: Marc Nuri --- test:refactor: SettableBeanPropertyDelegateTest doesn't rely on mocks Signed-off-by: Marc Nuri --- fix: SettableBeanPropertyDelegate implements all methods from SettableBeanProperty Includes tests to ensure all methods are implemented in future Jackson versions too. Signed-off-by: Marc Nuri Co-authored-by: Marc Nuri Signed-off-by: Marc Nuri --- CHANGELOG.md | 2 +- .../jackson/SettableBeanPropertyDelegate.java | 113 ++-- .../SettableBeanPropertyDelegateTest.java | 497 ++++++++++++++---- 3 files changed, 479 insertions(+), 133 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd8e45908e..eeca9ad641a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ #### Bugs * Fix #6247: Support for proxy authentication from proxy URL user info - +* Fix #6342: UnmatchedFieldTypeModule prevents certain jackson features from working ### 6.13.3 (2024-08-13) diff --git a/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegate.java b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegate.java index 021864e308a..8cf6b68a8e6 100644 --- a/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegate.java +++ b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegate.java @@ -16,36 +16,36 @@ package io.fabric8.kubernetes.model.jackson; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.PropertyName; +import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableAnyProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.exc.MismatchedInputException; -import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.introspect.ObjectIdInfo; +import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.function.BooleanSupplier; /** - * This concrete sub-class encapsulates a {@link SettableBeanProperty} delegate that is always tried first. + * This concrete subclass encapsulates a {@link SettableBeanProperty} delegate that is always tried first. * *

* A fall-back mechanism is implemented in the deserializeAndSet methods to allow field values that don't match the * target type to be preserved in the anySetter method if exists. */ -public class SettableBeanPropertyDelegate extends SettableBeanProperty { +public class SettableBeanPropertyDelegate extends SettableBeanProperty.Delegating { - private final SettableBeanProperty delegate; private final SettableAnyProperty anySetter; private final transient BooleanSupplier useAnySetter; SettableBeanPropertyDelegate(SettableBeanProperty delegate, SettableAnyProperty anySetter, BooleanSupplier useAnySetter) { super(delegate); - this.delegate = delegate; this.anySetter = anySetter; this.useAnySetter = useAnySetter; } @@ -54,64 +54,113 @@ public class SettableBeanPropertyDelegate extends SettableBeanProperty { * {@inheritDoc} */ @Override - public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { - return new SettableBeanPropertyDelegate(delegate.withValueDeserializer(deser), anySetter, useAnySetter); + protected SettableBeanProperty withDelegate(SettableBeanProperty d) { + return new SettableBeanPropertyDelegate(d, anySetter, useAnySetter); } /** * {@inheritDoc} */ @Override - public SettableBeanProperty withName(PropertyName newName) { - return new SettableBeanPropertyDelegate(delegate.withName(newName), anySetter, useAnySetter); + public void markAsIgnorable() { + delegate.markAsIgnorable(); } /** * {@inheritDoc} */ @Override - public SettableBeanProperty withNullProvider(NullValueProvider nva) { - return new SettableBeanPropertyDelegate(delegate.withNullProvider(nva), anySetter, useAnySetter); + public boolean isIgnorable() { + return delegate.isIgnorable(); } /** * {@inheritDoc} */ @Override - public AnnotatedMember getMember() { - return delegate.getMember(); + public void setViews(Class[] views) { + delegate.setViews(views); } /** * {@inheritDoc} */ @Override - public A getAnnotation(Class acls) { - return delegate.getAnnotation(acls); + public A getContextAnnotation(Class acls) { + return delegate.getContextAnnotation(acls); } /** * {@inheritDoc} */ @Override - public void fixAccess(DeserializationConfig config) { - delegate.fixAccess(config); + public PropertyName getWrapperName() { + return delegate.getWrapperName(); } /** * {@inheritDoc} */ @Override - public void markAsIgnorable() { - delegate.markAsIgnorable(); + public NullValueProvider getNullValueProvider() { + return delegate.getNullValueProvider(); } /** * {@inheritDoc} */ @Override - public boolean isIgnorable() { - return delegate.isIgnorable(); + public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) + throws JsonMappingException { + delegate.depositSchemaProperty(objectVisitor, provider); + } + + /** + * {@inheritDoc} + */ + @Override + public JavaType getType() { + return delegate.getType(); + } + + /** + * {@inheritDoc} + */ + @Override + public PropertyName getFullName() { + return delegate.getFullName(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setManagedReferenceName(String n) { + delegate.setManagedReferenceName(n); + } + + /** + * {@inheritDoc} + */ + @Override + public SettableBeanProperty withSimpleName(String simpleName) { + return _with(delegate.withSimpleName(simpleName)); + } + + /** + * {@inheritDoc} + */ + @Override + public void setObjectIdInfo(ObjectIdInfo objectIdInfo) { + delegate.setObjectIdInfo(objectIdInfo); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return delegate.toString(); } /** @@ -151,23 +200,7 @@ public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, } catch (MismatchedInputException ex) { deserializeAndSet(p, ctxt, instance); } - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public void set(Object instance, Object value) throws IOException { - delegate.set(instance, value); - } - - /** - * {@inheritDoc} - */ - @Override - public Object setAndReturn(Object instance, Object value) throws IOException { - return delegate.setAndReturn(instance, value); + return instance; } private boolean shouldUseAnySetter() { diff --git a/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegateTest.java b/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegateTest.java index f61d6f5f42e..240ecb8e6f4 100644 --- a/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegateTest.java +++ b/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/SettableBeanPropertyDelegateTest.java @@ -15,207 +15,520 @@ */ package io.fabric8.kubernetes.model.jackson; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyName; +import com.fasterxml.jackson.databind.deser.BeanDeserializer; +import com.fasterxml.jackson.databind.deser.BeanDeserializerFactory; +import com.fasterxml.jackson.databind.deser.CreatorProperty; +import com.fasterxml.jackson.databind.deser.DefaultDeserializationContext; +import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.SettableAnyProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; -import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import com.fasterxml.jackson.databind.deser.impl.FieldProperty; +import com.fasterxml.jackson.databind.deser.std.NumberDeserializers; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.introspect.BasicBeanDescription; +import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; +import com.fasterxml.jackson.databind.introspect.ObjectIdInfo; +import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; +import com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class SettableBeanPropertyDelegateTest { - private SettableBeanProperty delegateMock; - private SettableAnyProperty anySetterMock; - private SettableBeanPropertyDelegate settableBeanPropertyDelegate; private AtomicBoolean useAnySetter; + private ObjectMapper objectMapper; + private DefaultDeserializationContext deserializationContext; + private SettableAnyProperty anySetter; + private SettableBeanProperty intFieldProperty; + private SettableBeanPropertyDelegate intFieldPropertyDelegating; @BeforeEach - void setUp() { - delegateMock = mock(SettableBeanProperty.class, RETURNS_DEEP_STUBS); - anySetterMock = mock(SettableAnyProperty.class); + void setUp() throws Exception { useAnySetter = new AtomicBoolean(false); - settableBeanPropertyDelegate = new SettableBeanPropertyDelegate(delegateMock, anySetterMock, useAnySetter::get); + // Required Jackson deserialization objects to set up the test components + objectMapper = new ObjectMapper(); + final DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig(); + deserializationContext = new DefaultDeserializationContext.Impl(objectMapper.getDeserializationContext().getFactory()) + .createDummyInstance(deserializationConfig); + final JavaType testBeanJavaType = objectMapper.constructType(TestBean.class); + final BeanDescription testBeanDescription = deserializationConfig.introspect(testBeanJavaType); + final BeanDeserializer testBeanDeserializer = (BeanDeserializer) ((BeanDeserializerFactory) deserializationContext + .getFactory()) + .buildBeanDeserializer(deserializationContext, testBeanJavaType, testBeanDescription); + // AnySetter used by delegator, real instance that will invoke the additionalProperties any setter in TestBean + final BeanPropertyDefinition anySetterDefinition = SimpleBeanPropertyDefinition.construct(deserializationConfig, + testBeanDescription.findAnySetterAccessor()); + final BeanProperty anySetterProperty = new BeanProperty.Std( + anySetterDefinition.getFullName(), anySetterDefinition.getPrimaryType(), anySetterDefinition.getWrapperName(), + anySetterDefinition.getPrimaryMember(), anySetterDefinition.getMetadata()); + final JavaType anySetterValueType = objectMapper.constructType(Object.class); + anySetter = SettableAnyProperty.constructForMethod( + deserializationContext, anySetterProperty, anySetterProperty.getMember(), anySetterValueType, + deserializationContext.findKeyDeserializer(objectMapper.constructType(String.class), anySetterProperty), + deserializationContext.findRootValueDeserializer(anySetterValueType), null); + // Delegated SettableBeanProperty + intFieldProperty = testBeanDeserializer.findProperty("intField") + .withValueDeserializer(NumberDeserializers.find(int.class, null)); + // Delegating SettableBeanProperty in test + intFieldPropertyDelegating = new SettableBeanPropertyDelegate(intFieldProperty, anySetter, useAnySetter::get); + } @Test @DisplayName("withValueDeserializer, should return a new instance") void withValueDeserializer() { - // Given - doReturn(delegateMock).when(delegateMock).withValueDeserializer(any()); // When - final SettableBeanProperty result = settableBeanPropertyDelegate.withValueDeserializer(null); + final SettableBeanProperty result = intFieldPropertyDelegating.withValueDeserializer(null); // Then assertThat(result) .isInstanceOf(SettableBeanPropertyDelegate.class) - .isNotSameAs(settableBeanPropertyDelegate) - .hasFieldOrPropertyWithValue("anySetter", anySetterMock) - .hasFieldOrPropertyWithValue("delegate", delegateMock); + .isNotSameAs(intFieldPropertyDelegating) + .hasFieldOrPropertyWithValue("anySetter", anySetter) + .asInstanceOf(InstanceOfAssertFactories.type(SettableBeanPropertyDelegate.class)) + .extracting(SettableBeanPropertyDelegate::getDelegate) + .isInstanceOf(CreatorProperty.class) + .isNotSameAs(intFieldProperty) + .hasFieldOrPropertyWithValue("name", "intField"); } @Test @DisplayName("withName, should return a new instance") void withName() { - // Given - doReturn(delegateMock).when(delegateMock).withName(any()); // When - final SettableBeanProperty result = settableBeanPropertyDelegate.withName(null); + final SettableBeanProperty result = intFieldPropertyDelegating.withName(new PropertyName("overriddenName")); // Then assertThat(result) .isInstanceOf(SettableBeanPropertyDelegate.class) - .isNotSameAs(settableBeanPropertyDelegate) - .hasFieldOrPropertyWithValue("anySetter", anySetterMock) - .hasFieldOrPropertyWithValue("delegate", delegateMock); + .isNotSameAs(intFieldPropertyDelegating) + .hasFieldOrPropertyWithValue("anySetter", anySetter) + .asInstanceOf(InstanceOfAssertFactories.type(SettableBeanPropertyDelegate.class)) + .extracting(SettableBeanPropertyDelegate::getDelegate) + .isInstanceOf(CreatorProperty.class) + .isNotSameAs(intFieldProperty) + .hasFieldOrPropertyWithValue("name", "overriddenName"); } @Test @DisplayName("withNullProvider, should return a new instance") void withNullProvider() { - // Given - doReturn(delegateMock).when(delegateMock).withNullProvider(any()); // When - final SettableBeanProperty result = settableBeanPropertyDelegate.withNullProvider(null); + final SettableBeanProperty result = intFieldPropertyDelegating.withNullProvider(null); // Then assertThat(result) .isInstanceOf(SettableBeanPropertyDelegate.class) - .isNotSameAs(settableBeanPropertyDelegate) - .hasFieldOrPropertyWithValue("anySetter", anySetterMock) - .hasFieldOrPropertyWithValue("delegate", delegateMock); + .isNotSameAs(intFieldPropertyDelegating) + .hasFieldOrPropertyWithValue("anySetter", anySetter) + .asInstanceOf(InstanceOfAssertFactories.type(SettableBeanPropertyDelegate.class)) + .extracting(SettableBeanPropertyDelegate::getDelegate) + .isInstanceOf(CreatorProperty.class) + .isNotSameAs(intFieldProperty) + .hasFieldOrPropertyWithValue("name", "intField"); } @Test @DisplayName("getMember, should return delegate's Member") void getMember() { - // Given - when(delegateMock.getMember().getName()).thenReturn("the-member"); // When - final String result = settableBeanPropertyDelegate.getMember().getName(); + final AnnotatedMember result = intFieldPropertyDelegating.getMember(); + // Then + assertThat(result) + .isSameAs(intFieldProperty.getMember()) + .extracting(am -> am.getAnnotation(JsonProperty.class).value()) + .isEqualTo("intField"); + } + + @Test + @DisplayName("getCreatorIndex, should return delegate's creator index") + void getCreatorIndex() { + // When + final int result = intFieldPropertyDelegating.getCreatorIndex(); // Then - assertThat(result).isEqualTo("the-member"); + assertThat(result).isZero(); } @Test @DisplayName("getAnnotation, should return delegate's Annotation") void getAnnotation() { // When - settableBeanPropertyDelegate.getAnnotation(null); + final JsonProperty result = intFieldPropertyDelegating.getAnnotation(JsonProperty.class); // Then - verify(delegateMock, times(1)).getAnnotation(null); + assertThat(result) + .isSameAs(intFieldProperty.getAnnotation(JsonProperty.class)); } @Test @DisplayName("fixAccess, should invoke fixAccess in delegate") void fixAccess() { + // Given + final JavaType testBeanJavaType = objectMapper.constructType(TestBean.class); + final BasicBeanDescription testBeanDescription = (BasicBeanDescription) deserializationContext.getConfig() + .introspect(testBeanJavaType); + final BeanPropertyDefinition testPropertyFieldDefinition = (testBeanDescription) + .findProperty(PropertyName.construct("intField")); + final SettableBeanProperty fieldProperty = new FieldProperty(testPropertyFieldDefinition, testBeanJavaType, null, + testBeanDescription.getClassAnnotations(), testPropertyFieldDefinition.getField()); + final SettableBeanProperty fieldPropertyDelegating = new SettableBeanPropertyDelegate(fieldProperty, anySetter, + useAnySetter::get); + assertThat(((AccessibleObject) fieldProperty.getMember().getMember()).isAccessible()).isFalse(); // When - settableBeanPropertyDelegate.fixAccess(null); + fieldPropertyDelegating.fixAccess(deserializationContext.getConfig()); // Then - verify(delegateMock, times(1)).fixAccess(null); + assertThat(((AccessibleObject) fieldProperty.getMember().getMember()).isAccessible()).isTrue(); } @Test @DisplayName("markAsIgnorable, should invoke markAsIgnorable in delegate") void markAsIgnorable() { + // Given + assertThat(intFieldProperty.isIgnorable()).isFalse(); // When - settableBeanPropertyDelegate.markAsIgnorable(); + intFieldPropertyDelegating.markAsIgnorable(); // Then - verify(delegateMock, times(1)).markAsIgnorable(); + assertThat(intFieldProperty.isIgnorable()).isTrue(); } @Test @DisplayName("isIgnorable, should return isIgnorable result in delegate") void isIgnorable() { - // Given - when(delegateMock.isIgnorable()).thenReturn(true); // When - final boolean result = settableBeanPropertyDelegate.isIgnorable(); + final boolean result = intFieldPropertyDelegating.isIgnorable(); // Then - assertThat(result).isTrue(); + assertThat(result) + .isFalse() + .isEqualTo(intFieldProperty.isIgnorable()); } @Test - @DisplayName("set, should set in delegate") - void set() throws IOException { + @DisplayName("setViews, should invoke setViews in delegate") + void setViews() { // Given - final Object o1 = new Object(); - final Object o2 = new Object(); + assertThat(intFieldProperty.visibleInView(String.class)).isTrue(); // When - settableBeanPropertyDelegate.set(o1, o2); + intFieldPropertyDelegating.setViews(new Class[] { Integer.class }); // Then - verify(delegateMock, times(1)).set(o1, o2); + assertThat(intFieldProperty.visibleInView(String.class)).isFalse(); } @Test - @DisplayName("setAndReturn, should setAndReturn in delegate") - void setAndReturn() throws IOException { + @DisplayName("getContextAnnotation, should return getContextAnnotation result in delegate") + void getContextAnnotation() { + // When + final JsonIgnoreProperties result = intFieldPropertyDelegating + .getContextAnnotation(JsonIgnoreProperties.class); + // Then + assertThat(result) + .isSameAs(intFieldProperty.getContextAnnotation(JsonIgnoreProperties.class)) + .extracting(JsonIgnoreProperties::ignoreUnknown) + .isEqualTo(true); + } + + @Test + @DisplayName("getWrapperName, should return getWrapperName result in delegate") + void getWrapperName() { // Given - final Object o1 = new Object(); - final Object o2 = new Object(); + final DeserializationConfig config = deserializationContext.getConfig() + .withAppendedAnnotationIntrospector(new JacksonAnnotationIntrospector() { + @Override + public PropertyName findWrapperName(Annotated ann) { + return PropertyName.construct("WrapperNameForTest"); + } + }); + final JavaType testBeanJavaType = objectMapper.constructType(TestBean.class); + final BasicBeanDescription testBeanDescription = (BasicBeanDescription) config + .introspect(testBeanJavaType); + final BeanPropertyDefinition testPropertyFieldDefinition = (testBeanDescription) + .findProperty(PropertyName.construct("intField")); + final SettableBeanProperty fieldProperty = new FieldProperty(testPropertyFieldDefinition, testBeanJavaType, null, + testBeanDescription.getClassAnnotations(), testPropertyFieldDefinition.getField()); + final SettableBeanProperty fieldPropertyDelegating = new SettableBeanPropertyDelegate(fieldProperty, anySetter, + useAnySetter::get); // When - settableBeanPropertyDelegate.setAndReturn(o1, o2); + final PropertyName result = fieldPropertyDelegating.getWrapperName(); // Then - verify(delegateMock, times(1)).setAndReturn(o1, o2); + assertThat(result) + .isSameAs(fieldProperty.getWrapperName()) + .hasFieldOrPropertyWithValue("simpleName", "WrapperNameForTest"); + } + + @Test + @DisplayName("getNullValueProvider, should return getNullValueProvider result in delegate") + void getNullValueProvider() { + // When + final NullValueProvider result = intFieldPropertyDelegating.getNullValueProvider(); + // Then + assertThat(result) + .isSameAs(intFieldProperty.getNullValueProvider()); } @Test - @DisplayName("deserializeSetAndReturn, should deserializeSetAndReturn in delegate") - void deserializeSetAndReturn() throws IOException { + @DisplayName("depositSchemaProperty, should invoke depositSchemaProperty in delegate") + void depositSchemaProperty() throws Exception { // Given - final Object instance = new Object(); - when(delegateMock.deserializeSetAndReturn(any(), any(), eq(instance))).thenReturn("the-set-value"); + final JsonObjectFormatVisitor visitor = new JsonObjectFormatVisitor.Base() { + @Override + public void optionalProperty(BeanProperty prop) { + ((CreatorProperty) prop).setManagedReferenceName("visited"); + } + }; + // When + intFieldPropertyDelegating.depositSchemaProperty(visitor, objectMapper.getSerializerProvider()); + // Then + assertThat(intFieldProperty.getManagedReferenceName()) + .isEqualTo("visited"); + } + + @Test + @DisplayName("getFullName, should return getNullValueProvider result in delegate") + void getFullName() { + // When + final PropertyName result = intFieldPropertyDelegating.getFullName(); + // Then + assertThat(result) + .isSameAs(intFieldProperty.getFullName()) + .hasFieldOrPropertyWithValue("simpleName", "intField"); + } + + @Test + @DisplayName("setManagedReferenceName, should invoke setManagedReferenceName in delegate") + void setManagedReferenceName() { // When - final Object result = settableBeanPropertyDelegate.deserializeSetAndReturn(null, null, instance); + intFieldPropertyDelegating.setManagedReferenceName("the-managed-reference-name"); // Then - assertThat(result).isEqualTo("the-set-value"); + assertThat(intFieldPropertyDelegating.getManagedReferenceName()) + .isEqualTo(intFieldProperty.getManagedReferenceName()) + .isEqualTo("the-managed-reference-name"); } @Test - @DisplayName("deserializeSetAndReturn, with anySetter enabled and throws Exception, should use anySetter") - void deserializeSetAndReturnWithExceptionUsingAnySetter() throws IOException { + @DisplayName("setObjectIdInfo, should invoke setObjectIdInfo in delegate") + void setObjectIdInfo() { + // When + intFieldPropertyDelegating.setObjectIdInfo( + new ObjectIdInfo(PropertyName.construct("objectId"), null, null, null)); + // Then + assertThat(intFieldProperty.getObjectIdInfo()) + .extracting(ObjectIdInfo::getPropertyName) + .hasFieldOrPropertyWithValue("simpleName", "objectId"); + } + + @Test + @DisplayName("withSimpleName, should invoke withSimpleName in delegate") + void withSimpleName() { + // When + final SettableBeanProperty result = intFieldPropertyDelegating + .withSimpleName("overridden-simple-name"); + // Then + assertThat(result) + .isNotSameAs(intFieldPropertyDelegating) + .returns("overridden-simple-name", SettableBeanProperty::getName) + .extracting("delegate") + .asInstanceOf(InstanceOfAssertFactories.type(CreatorProperty.class)) + .isNotSameAs(intFieldProperty) + .returns("overridden-simple-name", SettableBeanProperty::getName); + } + + @Test + @DisplayName("toString, should return toString result in delegate") + void toStringTest() { + // When + final String result = intFieldPropertyDelegating.toString(); + // Then + assertThat(result) + .isEqualTo(intFieldProperty.toString()) + .isNotBlank(); + } + + @Test + @DisplayName("set, should set in delegate") + void set() throws IOException { // Given - final Object instance = new Object(); - when(delegateMock.getName()).thenReturn("the-property"); - when(delegateMock.deserializeSetAndReturn(any(), any(), eq(instance))) - .thenThrow(MismatchedInputException.from(null, Integer.class, "The Mocked Exception")); - doThrow(MismatchedInputException.from(null, Integer.class, "The delegate deserializeAndSet Exception")) - .when(delegateMock).deserializeAndSet(any(), any(), eq(instance)); - useAnySetter.set(true); + final TestBean instance = new TestBean(1337); + intFieldProperty.fixAccess(objectMapper.getDeserializationConfig()); // When - final Object result = settableBeanPropertyDelegate.deserializeSetAndReturn(mock(JsonParser.class), null, instance); + intFieldPropertyDelegating.set(instance, 313373); // Then - assertThat(result).isNull(); - verify(anySetterMock, times(1)).set(eq(instance), eq("the-property"), any()); + assertThat(instance) + .hasFieldOrPropertyWithValue("intField", 313373); } @Test - @DisplayName("deserializeSetAndReturn, with anySetter disabled and throws Exception, should throw Exception") - void deserializeSetAndReturnWithExceptionNotUsingAnySetter() throws IOException { + @DisplayName("setAndReturn, should setAndReturn in delegate") + void setAndReturn() throws IOException { // Given - final Object instance = new Object(); - when(delegateMock.getName()).thenReturn("the-property"); - when(delegateMock.deserializeSetAndReturn(any(), any(), eq(instance))) - .thenThrow(MismatchedInputException.from(null, Integer.class, "The Mocked Exception")); - doThrow(MismatchedInputException.from(null, Integer.class, "The delegate deserializeAndSet Exception")) - .when(delegateMock).deserializeAndSet(any(), any(), eq(instance)); + final TestBean instance = new TestBean(1337); + intFieldProperty.fixAccess(objectMapper.getDeserializationConfig()); // When - final MismatchedInputException result = assertThrows(MismatchedInputException.class, - () -> settableBeanPropertyDelegate.deserializeSetAndReturn(mock(JsonParser.class), null, instance)); + final Object result = intFieldPropertyDelegating.setAndReturn(instance, 313373); // Then - assertThat(result) - .hasMessage("The delegate deserializeAndSet Exception"); + assertThat(instance) + .hasFieldOrPropertyWithValue("intField", 313373) + .isSameAs(result); + } + + @Nested + @DisplayName("deserializeSetAndReturn") + class DeserializeSetAndReturn { + + private TestBean instance; + + @BeforeEach + void setUp() { + intFieldProperty.fixAccess(objectMapper.getDeserializationConfig()); + instance = new TestBean(1337); + } + + @Test + @DisplayName("validValue, should deserializeSetAndReturn in delegate") + void validValue() throws IOException { + try (JsonParser parser = objectMapper.createParser("313373")) { + final DefaultDeserializationContext ctx = deserializationContext + .createInstance(deserializationContext.getConfig(), parser, null); + parser.nextToken(); + final Object result = intFieldPropertyDelegating.deserializeSetAndReturn(parser, ctx, instance); + assertThat(instance) + .hasFieldOrPropertyWithValue("intField", 313373) + .isEqualTo(result); + } + } + + @Test + @DisplayName("deserializeSetAndReturn, with anySetter enabled and throws Exception, should use anySetter") + void invalidValueWithExceptionUsingAnySetter() throws IOException { + useAnySetter.set(true); + try (JsonParser parser = objectMapper.createParser("\"${a-placeholder}\"")) { + final DefaultDeserializationContext ctx = deserializationContext + .createInstance(deserializationContext.getConfig(), parser, null); + parser.nextToken(); + final Object result = intFieldPropertyDelegating.deserializeSetAndReturn(parser, ctx, instance); + assertThat(instance) + .hasFieldOrPropertyWithValue("intField", 1337) + .hasFieldOrPropertyWithValue("additionalProperties", Collections.singletonMap("intField", "${a-placeholder}")) + .isEqualTo(result); + } + } + + @Test + @DisplayName("deserializeSetAndReturn, with anySetter disabled and throws Exception, should throw Exception") + void deserializeSetAndReturnWithExceptionNotUsingAnySetter() throws IOException { + try (JsonParser parser = objectMapper.createParser("\"${a-placeholder}\"")) { + final DefaultDeserializationContext ctx = deserializationContext + .createInstance(deserializationContext.getConfig(), parser, null); + parser.nextToken(); + assertThatThrownBy(() -> intFieldPropertyDelegating.deserializeSetAndReturn(parser, ctx, instance)) + .isInstanceOf(InvalidFormatException.class) + .hasMessageContainingAll( + "Cannot deserialize value of type `int`", "\"${a-placeholder}\""); + } + } + + @Test + @DisplayName("deserializeSetAndReturn, with anySetter=null and throws Exception, should throw Exception") + void deserializeSetAndReturnWithExceptionAndNullAnySetter() throws IOException { + intFieldPropertyDelegating = new SettableBeanPropertyDelegate(intFieldProperty, null, () -> true); + try (JsonParser parser = objectMapper.createParser("\"${a-placeholder}\"")) { + final DefaultDeserializationContext ctx = deserializationContext + .createInstance(deserializationContext.getConfig(), parser, null); + parser.nextToken(); + assertThatThrownBy(() -> intFieldPropertyDelegating.deserializeSetAndReturn(parser, ctx, instance)) + .isInstanceOf(InvalidFormatException.class) + .hasMessageContainingAll( + "Cannot deserialize value of type `int`", "\"${a-placeholder}\""); + } + } + } + + @Nested + class ReflectionTest { + + @Test + @DisplayName("all methods from superclass (SettableBeanProperty) are implemented by delegating class (SettableBeanPropertyDelegate)") + void allMethodsFromSuperclassAreImplementedByDelegatingClass() { + final Map superclassMethods = Stream.of(SettableBeanProperty.class.getDeclaredMethods()) + .filter(m -> !Modifier.isFinal(m.getModifiers())) + .filter(m -> !Modifier.isPrivate(m.getModifiers())) + .filter(m -> !Modifier.isAbstract(m.getModifiers())) + .filter(m -> !m.getName().startsWith("_")) + .map(MethodSignature::from) + .collect(Collectors.toMap(ms -> ms, ms -> false)); + Stream.concat( + Stream.of(SettableBeanProperty.Delegating.class.getDeclaredMethods()), + Stream.of(SettableBeanPropertyDelegate.class.getDeclaredMethods())) + .map(MethodSignature::from) + .forEach(ms -> superclassMethods.computeIfPresent(ms, (k, v) -> true)); + assertThat(superclassMethods) + .values() + .containsOnly(true); + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + private static final class TestBean { + + @JsonProperty("intField") + int intField; + private final Map additionalProperties; + + @JsonCreator + private TestBean(@JsonProperty("intField") int intField) { + this.intField = intField; + additionalProperties = new LinkedHashMap<>(); + } + + @JsonAnyGetter + private Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + private void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + } + + @AllArgsConstructor + @EqualsAndHashCode + private static final class MethodSignature { + private final Class returnType; + private final String name; + private final Class[] parameterTypes; + + private static MethodSignature from(Method m) { + return new MethodSignature(m.getReturnType(), m.getName(), m.getParameterTypes()); + } + } } From 71354a8d12a0cec3aabd28ca12efaf7c8e35b383 Mon Sep 17 00:00:00 2001 From: Steven Hawkins Date: Fri, 20 Sep 2024 11:22:32 +0200 Subject: [PATCH 3/6] fix: moving source close to the executor (just like doConsume) close: #6354 Signed-off-by: Steve Hawkins Signed-off-by: Marc Nuri --- CHANGELOG.md | 1 + .../fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eeca9ad641a..24daa32301b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ #### Bugs * Fix #6247: Support for proxy authentication from proxy URL user info * Fix #6342: UnmatchedFieldTypeModule prevents certain jackson features from working +* Fix #6354: Prevent deadlock in okhttp AsyncBody.cancel ### 6.13.3 (2024-08-13) diff --git a/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java b/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java index 81a88396fef..a267630893d 100644 --- a/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java +++ b/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java @@ -151,7 +151,10 @@ public CompletableFuture done() { @Override public void cancel() { - Utils.closeQuietly(source); + // closing from a non dispatcher thread risks deadlock because close is + // a long-running operation that may need to re-obtain the dispatcher lock + // and the thread may already be holding other locks + executor.execute(() -> Utils.closeQuietly(source)); done.cancel(false); } } From b3b22cb4c2e288ec7066ae730fea0717770629c9 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Wed, 25 Sep 2024 13:26:10 +0800 Subject: [PATCH 4/6] fix: allowing the usage of authenticated http proxies for https (6371) fix: allowing the usage of authenticated http proxies for https --- review: remove duplicate proxy init in Jetty Co-authored-by: Steven Hawkins --- .../client/jetty/JettyHttpClientBuilder.java | 25 +++- .../jetty/JettyHttpClientProxyHttpsTest.java | 27 ++++ .../okhttp/OkHttpClientProxyHttpsTest.java | 35 +++++ .../client/okhttp/OkHttpClientProxyTest.java | 3 +- .../client/vertx/VertxHttpClientBuilder.java | 12 +- .../vertx/VertxHttpClientProxyHttpsTest.java | 27 ++++ .../client/utils/HttpClientUtils.java | 18 +++ .../AbstractHttpClientProxyHttpsTest.java | 129 ++++++++++++++++++ .../http/AbstractHttpClientProxyTest.java | 53 ++++++- 9 files changed, 319 insertions(+), 10 deletions(-) create mode 100644 httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientProxyHttpsTest.java create mode 100644 httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyHttpsTest.java create mode 100644 httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientProxyHttpsTest.java create mode 100644 kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyHttpsTest.java diff --git a/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java b/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java index 0935ab8a234..ff1effba731 100644 --- a/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java +++ b/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java @@ -24,19 +24,26 @@ import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.Origin; import org.eclipse.jetty.client.Socks4Proxy; +import org.eclipse.jetty.client.Socks5Proxy; +import org.eclipse.jetty.client.api.Authentication; import org.eclipse.jetty.client.dynamic.HttpClientTransportDynamic; import org.eclipse.jetty.client.http.HttpClientConnectionFactory; import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; +import org.eclipse.jetty.client.util.BasicAuthentication; import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.http.ClientConnectionFactoryOverHTTP2; import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.websocket.client.WebSocketClient; +import java.net.URI; +import java.net.URISyntaxException; import java.time.Duration; import java.util.Optional; import java.util.stream.Stream; +import static io.fabric8.kubernetes.client.utils.HttpClientUtils.decodeBasicCredentials; + public class JettyHttpClientBuilder extends StandardHttpClientBuilder { @@ -91,11 +98,25 @@ public JettyHttpClient build() { case SOCKS4: sharedHttpClient.getProxyConfiguration().addProxy(new Socks4Proxy(address, false)); break; + case SOCKS5: + sharedHttpClient.getProxyConfiguration().addProxy(new Socks5Proxy(address, false)); + break; default: throw new KubernetesClientException("Unsupported proxy type"); } - sharedHttpClient.getProxyConfiguration().addProxy(new HttpProxy(address, false)); - addProxyAuthInterceptor(); + final String[] userPassword = decodeBasicCredentials(this.proxyAuthorization); + if (userPassword != null) { + URI proxyUri; + try { + proxyUri = new URI("http://" + proxyAddress.getHostString() + ":" + proxyAddress.getPort()); + } catch (URISyntaxException e) { + throw KubernetesClientException.launderThrowable(e); + } + sharedHttpClient.getAuthenticationStore() + .addAuthentication(new BasicAuthentication(proxyUri, Authentication.ANY_REALM, userPassword[0], userPassword[1])); + } else { + addProxyAuthInterceptor(); + } } clientFactory.additionalConfig(sharedHttpClient, sharedWebSocketClient); return new JettyHttpClient(this, sharedHttpClient, sharedWebSocketClient); diff --git a/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientProxyHttpsTest.java b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientProxyHttpsTest.java new file mode 100644 index 00000000000..230f9f3ce76 --- /dev/null +++ b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientProxyHttpsTest.java @@ -0,0 +1,27 @@ +/* + * 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.jetty; + +import io.fabric8.kubernetes.client.http.AbstractHttpClientProxyHttpsTest; +import io.fabric8.kubernetes.client.http.HttpClient; + +@SuppressWarnings("java:S2187") +public class JettyHttpClientProxyHttpsTest extends AbstractHttpClientProxyHttpsTest { + @Override + protected HttpClient.Factory getHttpClientFactory() { + return new JettyHttpClientFactory(); + } +} diff --git a/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyHttpsTest.java b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyHttpsTest.java new file mode 100644 index 00000000000..92cb39663e5 --- /dev/null +++ b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyHttpsTest.java @@ -0,0 +1,35 @@ +/* + * 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.okhttp; + +import io.fabric8.kubernetes.client.http.AbstractHttpClientProxyHttpsTest; +import io.fabric8.kubernetes.client.http.HttpClient; +import okhttp3.OkHttpClient.Builder; + +@SuppressWarnings("java:S2187") +public class OkHttpClientProxyHttpsTest extends AbstractHttpClientProxyHttpsTest { + @Override + protected HttpClient.Factory getHttpClientFactory() { + return new OkHttpClientFactory() { + @Override + protected Builder newOkHttpClientBuilder() { + Builder builder = super.newOkHttpClientBuilder(); + builder.hostnameVerifier((hostname, session) -> true); + return builder; + } + }; + } +} diff --git a/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyTest.java b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyTest.java index 7b76a1e7e81..9972a2db619 100644 --- a/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyTest.java +++ b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientProxyTest.java @@ -26,8 +26,7 @@ protected HttpClient.Factory getHttpClientFactory() { } @Override - protected void proxyConfigurationAddsRequiredHeaders() { - // NO-OP + protected void proxyConfigurationOtherAuthAddsRequiredHeaders() throws Exception { // OkHttp uses a response intercept to add the auth proxy headers in case the original response failed } } diff --git a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java index 7ff55ec8d3a..5b6e63e17e2 100644 --- a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java +++ b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java @@ -36,6 +36,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; +import static io.fabric8.kubernetes.client.utils.HttpClientUtils.decodeBasicCredentials; + public class VertxHttpClientBuilder extends StandardHttpClientBuilder, F, VertxHttpClientBuilder> { @@ -74,12 +76,18 @@ public VertxHttpClient build() { } if (this.proxyType != HttpClient.ProxyType.DIRECT && this.proxyAddress != null) { - ProxyOptions proxyOptions = new ProxyOptions() + final ProxyOptions proxyOptions = new ProxyOptions() .setHost(this.proxyAddress.getHostName()) .setPort(this.proxyAddress.getPort()) .setType(convertProxyType()); + final String[] userPassword = decodeBasicCredentials(this.proxyAuthorization); + if (userPassword != null) { + proxyOptions.setUsername(userPassword[0]); + proxyOptions.setPassword(userPassword[1]); + } else { + addProxyAuthInterceptor(); + } options.setProxyOptions(proxyOptions); - addProxyAuthInterceptor(); } final String[] protocols; diff --git a/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientProxyHttpsTest.java b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientProxyHttpsTest.java new file mode 100644 index 00000000000..c93b80b9789 --- /dev/null +++ b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientProxyHttpsTest.java @@ -0,0 +1,27 @@ +/* + * 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.vertx; + +import io.fabric8.kubernetes.client.http.AbstractHttpClientProxyHttpsTest; +import io.fabric8.kubernetes.client.http.HttpClient; + +@SuppressWarnings("java:S2187") +public class VertxHttpClientProxyHttpsTest extends AbstractHttpClientProxyHttpsTest { + @Override + protected HttpClient.Factory getHttpClientFactory() { + return new VertxHttpClientFactory(); + } +} diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java index d98d71d2ef8..0d27ffdc8a0 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java @@ -132,6 +132,24 @@ public static String basicCredentials(String username, String password) { return basicCredentials(username + ":" + password); } + public static String[] decodeBasicCredentials(String basicCredentials) { + if (basicCredentials == null) { + return null; + } + try { + final String encodedCredentials = basicCredentials.replaceFirst("Basic ", ""); + final String decodedProxyAuthorization = new String(Base64.getDecoder().decode(encodedCredentials), + StandardCharsets.UTF_8); + final String[] userPassword = decodedProxyAuthorization.split(":"); + if (userPassword.length == 2) { + return userPassword; + } + } catch (Exception ignored) { + // Ignored + } + return null; + } + /** * @deprecated you should not need to call this method directly. Please create your own HttpClient.Factory * should you need to customize your clients. diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyHttpsTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyHttpsTest.java new file mode 100644 index 00000000000..fe7b8c059f7 --- /dev/null +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyHttpsTest.java @@ -0,0 +1,129 @@ +/* + * 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.http; + +import io.fabric8.kubernetes.client.internal.SSLUtils; +import io.fabric8.mockwebserver.Context; +import io.fabric8.mockwebserver.DefaultMockServer; +import io.fabric8.mockwebserver.ServerRequest; +import io.fabric8.mockwebserver.ServerResponse; +import io.fabric8.mockwebserver.dsl.HttpMethod; +import io.fabric8.mockwebserver.internal.MockDispatcher; +import io.fabric8.mockwebserver.internal.MockSSLContextFactory; +import io.fabric8.mockwebserver.internal.SimpleRequest; +import io.fabric8.mockwebserver.internal.SimpleResponse; +import io.fabric8.mockwebserver.utils.ResponseProvider; +import okhttp3.Headers; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import okhttp3.mockwebserver.SocketPolicy; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.net.InetSocketAddress; +import java.util.ArrayDeque; +import java.util.HashMap; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static io.fabric8.kubernetes.client.utils.HttpClientUtils.basicCredentials; +import static org.assertj.core.api.Assertions.assertThat; + +public abstract class AbstractHttpClientProxyHttpsTest { + + private static SocketPolicy defaultResponseSocketPolicy; + private static Map> responses; + private static DefaultMockServer server; + + @BeforeAll + static void beforeAll() { + defaultResponseSocketPolicy = SocketPolicy.KEEP_OPEN; + responses = new HashMap<>(); + final MockWebServer okHttpMockWebServer = new MockWebServer(); + final MockDispatcher dispatcher = new MockDispatcher(responses) { + @Override + public MockResponse peek() { + return new MockResponse().setSocketPolicy(defaultResponseSocketPolicy); + } + }; + server = new DefaultMockServer(new Context(), okHttpMockWebServer, responses, dispatcher, true); + server.start(); + okHttpMockWebServer.useHttps(MockSSLContextFactory.create().getSocketFactory(), true); + } + + @AfterAll + static void afterAll() { + server.shutdown(); + } + + protected abstract HttpClient.Factory getHttpClientFactory(); + + @Test + @DisplayName("Proxied HttpClient adds required headers to the request") + protected void proxyConfigurationAddsRequiredHeadersForHttps() throws Exception { + final AtomicReference initialConnectRequest = new AtomicReference<>(); + final ResponseProvider bodyProvider = new ResponseProvider() { + + @Override + public String getBody(RecordedRequest request) { + return ""; + } + + @Override + public void setHeaders(Headers headers) { + } + + @Override + public int getStatusCode(RecordedRequest request) { + defaultResponseSocketPolicy = SocketPolicy.UPGRADE_TO_SSL_AT_END; // for jetty to upgrade after the challenge + if (request.getHeader(StandardHttpHeaders.PROXY_AUTHORIZATION) != null) { + initialConnectRequest.compareAndSet(null, request); + return 200; + } + return 407; + } + + @Override + public Headers getHeaders() { + return new Headers.Builder().add("Proxy-Authenticate", "Basic").build(); + } + + }; + responses.computeIfAbsent(new SimpleRequest(HttpMethod.CONNECT, "/"), k -> new ArrayDeque<>()) + .add(new SimpleResponse(true, bodyProvider, null, 0, TimeUnit.SECONDS)); + // Given + final HttpClient.Builder builder = getHttpClientFactory().newBuilder() + .sslContext(null, SSLUtils.trustManagers(null, null, true, null, null)) + .proxyAddress(new InetSocketAddress("localhost", server.getPort())) + .proxyAuthorization(basicCredentials("auth", "cred")); + try (HttpClient client = builder.build()) { + // When + client.sendAsync(client.newHttpRequestBuilder() + .uri(String.format("https://0.0.0.0:%s/not-found", server.getPort() + 1)).build(), String.class) + .get(30, TimeUnit.SECONDS); + + // if it fails, then authorization was not set + assertThat(initialConnectRequest) + .doesNotHaveNullValue() + .hasValueMatching(r -> r.getHeader("Proxy-Authorization").equals("Basic YXV0aDpjcmVk")); + } + } +} diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyTest.java index d977a097e4b..c04397ad8aa 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpClientProxyTest.java @@ -16,6 +16,8 @@ package io.fabric8.kubernetes.client.http; import io.fabric8.mockwebserver.DefaultMockServer; +import io.fabric8.mockwebserver.utils.ResponseProvider; +import okhttp3.Headers; import okhttp3.mockwebserver.RecordedRequest; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -25,6 +27,7 @@ import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; +import static io.fabric8.kubernetes.client.utils.HttpClientUtils.basicCredentials; import static org.assertj.core.api.Assertions.assertThat; public abstract class AbstractHttpClientProxyTest { @@ -45,12 +48,54 @@ static void afterAll() { protected abstract HttpClient.Factory getHttpClientFactory(); @Test - @DisplayName("Proxied HttpClient adds required headers to the request") - protected void proxyConfigurationAddsRequiredHeaders() throws Exception { + @DisplayName("Proxied HttpClient with basic authorization adds required headers to the request") + protected void proxyConfigurationBasicAuthAddsRequiredHeaders() throws Exception { + server.expect().get().withPath("/").andReply(new ResponseProvider() { + + @Override + public String getBody(RecordedRequest request) { + return "\n"; + } + + @Override + public void setHeaders(Headers headers) { + } + + @Override + public int getStatusCode(RecordedRequest request) { + return request.getHeader(StandardHttpHeaders.PROXY_AUTHORIZATION) != null ? 200 : 407; + } + + @Override + public Headers getHeaders() { + return new Headers.Builder().add("Proxy-Authenticate", "Basic").build(); + } + + }).always(); + // Given + final HttpClient.Builder builder = getHttpClientFactory().newBuilder() + .proxyAddress(new InetSocketAddress("localhost", server.getPort())) + .proxyAuthorization(basicCredentials("auth", "cred")); + try (HttpClient client = builder.build()) { + // When + client.sendAsync(client.newHttpRequestBuilder() + .uri(String.format("http://0.0.0.0:%s/not-found", server.getPort())).build(), String.class) + .get(10L, TimeUnit.SECONDS); + // Then + assertThat(server.getLastRequest()) + .extracting(RecordedRequest::getHeaders) + .returns("0.0.0.0:" + server.getPort(), h -> h.get("Host")) + .returns("Basic YXV0aDpjcmVk", h -> h.get("Proxy-Authorization")); + } + } + + @Test + @DisplayName("Proxied HttpClient with other authorization adds required headers to the request") + protected void proxyConfigurationOtherAuthAddsRequiredHeaders() throws Exception { // Given final HttpClient.Builder builder = getHttpClientFactory().newBuilder() .proxyAddress(new InetSocketAddress("localhost", server.getPort())) - .proxyAuthorization("auth:cred"); + .proxyAuthorization("Other kind of auth"); try (HttpClient client = builder.build()) { // When client.sendAsync(client.newHttpRequestBuilder() @@ -60,7 +105,7 @@ protected void proxyConfigurationAddsRequiredHeaders() throws Exception { assertThat(server.getLastRequest()) .extracting(RecordedRequest::getHeaders) .returns("0.0.0.0:" + server.getPort(), h -> h.get("Host")) - .returns("auth:cred", h -> h.get("Proxy-Authorization")); + .returns("Other kind of auth", h -> h.get("Proxy-Authorization")); } } } From ae56f30170c490e1efca21fa6ae4e022d5133d1a Mon Sep 17 00:00:00 2001 From: Steven Hawkins Date: Wed, 25 Sep 2024 09:21:40 +0200 Subject: [PATCH 5/6] fix: use the Retry-After header value closes: #6366 Signed-off-by: Steve Hawkins Signed-off-by: Marc Nuri --- CHANGELOG.md | 1 + .../client/http/StandardHttpClient.java | 57 ++++++++++--------- .../kubernetes/client/utils/AsyncUtils.java | 10 +++- .../client/http/StandardHttpClientTest.java | 18 ++++++ .../client/utils/AsyncUtilsTest.java | 8 +-- 5 files changed, 60 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24daa32301b..5a6e41f4e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Fix #6247: Support for proxy authentication from proxy URL user info * Fix #6342: UnmatchedFieldTypeModule prevents certain jackson features from working * Fix #6354: Prevent deadlock in okhttp AsyncBody.cancel +* Fix #6366: Allow Retry-After header to be considered in retries ### 6.13.3 (2024-08-13) diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java index 1a415681f0c..80c0f42048c 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java @@ -27,7 +27,6 @@ import java.io.Closeable; import java.io.IOException; -import java.net.URI; import java.nio.ByteBuffer; import java.time.Duration; import java.time.ZonedDateTime; @@ -152,7 +151,6 @@ private CompletableFuture> consumeBytesOnce(StandardHttp private CompletableFuture retryWithExponentialBackoff( StandardHttpRequest request, Supplier> action, java.util.function.Consumer onCancel, Function> responseExtractor) { - final URI uri = request.uri(); final RequestConfig requestConfig = getTag(RequestConfig.class); final ExponentialBackoffIntervalCalculator retryIntervalCalculator = ExponentialBackoffIntervalCalculator .from(requestConfig); @@ -164,34 +162,39 @@ private CompletableFuture retryWithExponentialBackoff( } return AsyncUtils.retryWithExponentialBackoff(action, onCancel, timeout, retryIntervalCalculator, (response, throwable, retryInterval) -> { - if (response != null) { - HttpResponse httpResponse = responseExtractor.apply(response); - if (httpResponse != null) { - final int code = httpResponse.code(); - if (code == 429 || code >= 500) { - retryInterval = Math.max(retryAfterMillis(httpResponse), retryInterval); - LOG.debug( - "HTTP operation on url: {} should be retried as the response code was {}, retrying after {} millis", - uri, code, retryInterval); - return true; - } - } - } else { - final Throwable actualCause = unwrapCompletionException(throwable); - builder.interceptors.forEach((s, interceptor) -> interceptor.afterConnectionFailure(request, actualCause)); - if (actualCause instanceof IOException) { - // TODO: may not be specific enough - incorrect ssl settings for example will get caught here - LOG.debug( - String.format("HTTP operation on url: %s should be retried after %d millis because of IOException", - uri, retryInterval), - actualCause); - return true; - } - } - return false; + return shouldRetry(request, responseExtractor, response, throwable, retryInterval); }); } + long shouldRetry(StandardHttpRequest request, Function> responseExtractor, V response, + Throwable throwable, long retryInterval) { + if (response != null) { + HttpResponse httpResponse = responseExtractor.apply(response); + if (httpResponse != null) { + final int code = httpResponse.code(); + if (code == 429 || code >= 500) { + retryInterval = Math.max(retryAfterMillis(httpResponse), retryInterval); + LOG.debug( + "HTTP operation on url: {} should be retried as the response code was {}, retrying after {} millis", + request.uri(), code, retryInterval); + return retryInterval; + } + } + } else { + final Throwable actualCause = unwrapCompletionException(throwable); + builder.interceptors.forEach((s, interceptor) -> interceptor.afterConnectionFailure(request, actualCause)); + if (actualCause instanceof IOException) { + // TODO: may not be specific enough - incorrect ssl settings for example will get caught here + LOG.debug( + String.format("HTTP operation on url: %s should be retried after %d millis because of IOException", + request.uri(), retryInterval), + actualCause); + return retryInterval; + } + } + return -1; + } + static Throwable unwrapCompletionException(Throwable throwable) { final Throwable actualCause; if (throwable instanceof CompletionException) { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/AsyncUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/AsyncUtils.java index 1c6331bd49b..0f079cb67c5 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/AsyncUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/AsyncUtils.java @@ -49,7 +49,7 @@ public static CompletableFuture withTimeout(CompletableFuture future, /** * Returns a new {@link CompletableFuture} that will complete once the action provided by the action supplier completes. * The action will be retried with an exponential backoff using the {@link ExponentialBackoffIntervalCalculator} as - * long as the {@link ShouldRetry} predicate returns true. + * long as the {@link ShouldRetry} predicate returns a non-negative value. * Each action retrieval retry will time out after the provided timeout {@link Duration}. * * @param action the action supplier. @@ -75,7 +75,8 @@ private static void retryWithExponentialBackoff(CompletableFuture result, withTimeout(action.get(), timeout).whenComplete((r, t) -> { if (retryIntervalCalculator.shouldRetry() && !result.isDone()) { final long retryInterval = retryIntervalCalculator.nextReconnectInterval(); - if (shouldRetry.shouldRetry(r, t, retryInterval)) { + long retryValue = shouldRetry.shouldRetry(r, t, retryInterval); + if (retryValue >= 0) { if (r != null) { onCancel.accept(r); } @@ -95,6 +96,9 @@ private static void retryWithExponentialBackoff(CompletableFuture result, @FunctionalInterface public interface ShouldRetry { - boolean shouldRetry(T result, Throwable exception, long retryInterval); + /** + * @return the retry interval in ms, or a negative value indicating retries should be aborted + */ + long shouldRetry(T result, Throwable exception, long retryInterval); } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java index 387f6aefacf..24a983e35a8 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java @@ -32,7 +32,9 @@ import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; @@ -178,6 +180,22 @@ void testHttpRetryWithLessFailuresThanRetries() throws Exception { .hasSize(4); } + @Test + void testShouldRetryUsesRetryAfterHeader() throws Exception { + client = client.newBuilder().tag(new RequestConfigBuilder() + .withRequestRetryBackoffLimit(3) + .withRequestRetryBackoffInterval(50).build()) + .build(); + + Map> headers = new HashMap<>(); + headers.put(StandardHttpHeaders.RETRY_AFTER, Arrays.asList("5")); + // the exception type doesn't matter + final WebSocketResponse error = new WebSocketResponse(new WebSocketUpgradeResponse(null, 429, headers), new IOException()); + + assertThat(client.shouldRetry((StandardHttpRequest) client.newHttpRequestBuilder().uri("http://localhost").build(), + r -> r.webSocketUpgradeResponse, error, null, 1000)).isEqualTo(5000); + } + @Test void testWebSocketWithLessFailuresThanRetries() throws Exception { client = client.newBuilder().tag(new RequestConfigBuilder() diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/AsyncUtilsTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/AsyncUtilsTest.java index f648d4c2c5a..c10f482bfd8 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/AsyncUtilsTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/AsyncUtilsTest.java @@ -79,7 +79,7 @@ void retryWithExponentialBackoff_timeout() { final Supplier> action = CompletableFuture::new; final CompletableFuture onCancel = new CompletableFuture<>(); final ExponentialBackoffIntervalCalculator retryIntervalCalculator = new ExponentialBackoffIntervalCalculator(1, 1); - final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> true; + final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> retryInterval; // When final CompletableFuture result = retryWithExponentialBackoff(action, onCancel::complete, Duration.ofMillis(1), retryIntervalCalculator, shouldRetry); @@ -98,7 +98,7 @@ void retryWithExponentialBackoff_withCancelledFuture_onCancel() { final Supplier> actionSupplier = () -> action; final CompletableFuture onCancel = new CompletableFuture<>(); final ExponentialBackoffIntervalCalculator retryIntervalCalculator = new ExponentialBackoffIntervalCalculator(1, 0); - final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> false; + final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> -1; // When final CompletableFuture result = retryWithExponentialBackoff(actionSupplier, onCancel::complete, Duration.ofMillis(100), retryIntervalCalculator, shouldRetry); @@ -119,7 +119,7 @@ void retryWithExponentialBackoff_withCompletedResult_onCancel() throws Exception final Supplier> actionSupplier = () -> action; final CompletableFuture onCancel = new CompletableFuture<>(); final ExponentialBackoffIntervalCalculator retryIntervalCalculator = new ExponentialBackoffIntervalCalculator(1, 1); - final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> true; + final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> retryInterval; // When CompletableFuture result = retryWithExponentialBackoff(actionSupplier, onCancel::complete, Duration.ofMillis(100), retryIntervalCalculator, shouldRetry); @@ -140,7 +140,7 @@ void retryWithExponentialBackoff_complete() { final Supplier> actionSupplier = () -> action; final CompletableFuture onCancel = new CompletableFuture<>(); final ExponentialBackoffIntervalCalculator retryIntervalCalculator = new ExponentialBackoffIntervalCalculator(1, 0); - final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> false; + final AsyncUtils.ShouldRetry shouldRetry = (v, t, retryInterval) -> -1; // When final CompletableFuture result = retryWithExponentialBackoff(actionSupplier, onCancel::complete, Duration.ofMillis(100), retryIntervalCalculator, shouldRetry); From 6ee190c3a36ea6ae5ed7513942e2cabef177a0eb Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Wed, 25 Sep 2024 09:48:51 +0200 Subject: [PATCH 6/6] [RELEASE] Updated project version to v6.13.4 Signed-off-by: Marc Nuri --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- CHANGELOG.md | 1 + chaos-tests/pom.xml | 2 +- crd-generator/api-v2/pom.xml | 2 +- crd-generator/api/pom.xml | 2 +- crd-generator/apt/pom.xml | 2 +- crd-generator/pom.xml | 2 +- crd-generator/test-apt/pom.xml | 2 +- crd-generator/test/pom.xml | 2 +- extensions/certmanager/client/pom.xml | 2 +- extensions/certmanager/examples/pom.xml | 2 +- extensions/certmanager/model-v1/pom.xml | 2 +- extensions/certmanager/model-v1alpha2/pom.xml | 2 +- extensions/certmanager/model-v1alpha3/pom.xml | 2 +- extensions/certmanager/model-v1beta1/pom.xml | 2 +- extensions/certmanager/pom.xml | 2 +- extensions/certmanager/tests/pom.xml | 2 +- extensions/chaosmesh/client/pom.xml | 2 +- extensions/chaosmesh/examples/pom.xml | 2 +- extensions/chaosmesh/model/pom.xml | 2 +- extensions/chaosmesh/pom.xml | 2 +- extensions/chaosmesh/tests/pom.xml | 2 +- extensions/istio/client/pom.xml | 2 +- extensions/istio/examples/pom.xml | 2 +- extensions/istio/model-v1alpha3/pom.xml | 2 +- extensions/istio/model-v1beta1/pom.xml | 2 +- extensions/istio/pom.xml | 2 +- extensions/istio/tests/pom.xml | 2 +- extensions/knative/client/pom.xml | 2 +- extensions/knative/examples/pom.xml | 2 +- extensions/knative/model/pom.xml | 2 +- extensions/knative/pom.xml | 2 +- extensions/knative/tests/pom.xml | 2 +- extensions/open-cluster-management/client/pom.xml | 2 +- extensions/open-cluster-management/examples/pom.xml | 2 +- extensions/open-cluster-management/model-agent/pom.xml | 2 +- extensions/open-cluster-management/model-apps/pom.xml | 2 +- extensions/open-cluster-management/model-cluster/pom.xml | 2 +- extensions/open-cluster-management/model-discovery/pom.xml | 2 +- .../open-cluster-management/model-observability/pom.xml | 2 +- extensions/open-cluster-management/model-operator/pom.xml | 2 +- .../open-cluster-management/model-placementruleapps/pom.xml | 2 +- extensions/open-cluster-management/model-policy/pom.xml | 2 +- extensions/open-cluster-management/model-search/pom.xml | 2 +- extensions/open-cluster-management/pom.xml | 2 +- extensions/open-cluster-management/tests/pom.xml | 2 +- extensions/open-virtual-networking/client/pom.xml | 2 +- extensions/open-virtual-networking/model-v1/pom.xml | 2 +- extensions/open-virtual-networking/pom.xml | 2 +- extensions/open-virtual-networking/tests/pom.xml | 2 +- extensions/pom.xml | 2 +- extensions/service-catalog/client/pom.xml | 2 +- extensions/service-catalog/examples/pom.xml | 2 +- extensions/service-catalog/model/pom.xml | 2 +- extensions/service-catalog/pom.xml | 2 +- extensions/service-catalog/tests/pom.xml | 2 +- extensions/tekton/client/pom.xml | 2 +- extensions/tekton/examples/pom.xml | 2 +- extensions/tekton/model-triggers-v1alpha1/pom.xml | 2 +- extensions/tekton/model-triggers-v1beta1/pom.xml | 2 +- extensions/tekton/model-v1/pom.xml | 2 +- extensions/tekton/model-v1alpha1/pom.xml | 2 +- extensions/tekton/model-v1beta1/pom.xml | 2 +- extensions/tekton/pom.xml | 2 +- extensions/tekton/tests/pom.xml | 2 +- extensions/verticalpodautoscaler/client/pom.xml | 2 +- extensions/verticalpodautoscaler/examples/pom.xml | 2 +- extensions/verticalpodautoscaler/model-v1/pom.xml | 2 +- extensions/verticalpodautoscaler/pom.xml | 2 +- extensions/verticalpodautoscaler/tests/pom.xml | 2 +- extensions/volcano/client/pom.xml | 2 +- extensions/volcano/examples/pom.xml | 2 +- extensions/volcano/model-v1beta1/pom.xml | 2 +- extensions/volcano/pom.xml | 2 +- extensions/volcano/tests/pom.xml | 2 +- extensions/volumesnapshot/client/pom.xml | 2 +- extensions/volumesnapshot/examples/pom.xml | 2 +- extensions/volumesnapshot/model/pom.xml | 2 +- extensions/volumesnapshot/pom.xml | 2 +- extensions/volumesnapshot/tests/pom.xml | 2 +- generator-annotations/pom.xml | 2 +- httpclient-jdk/pom.xml | 2 +- httpclient-jetty/pom.xml | 2 +- httpclient-okhttp/pom.xml | 2 +- httpclient-tests/pom.xml | 2 +- httpclient-vertx/pom.xml | 2 +- java-generator/benchmark/pom.xml | 2 +- java-generator/cli/pom.xml | 2 +- java-generator/core/pom.xml | 2 +- java-generator/gradle-plugin/pom.xml | 2 +- java-generator/it/pom.xml | 2 +- java-generator/maven-plugin/pom.xml | 2 +- java-generator/pom.xml | 2 +- junit/kube-api-test/client-inject/pom.xml | 2 +- junit/kube-api-test/core/pom.xml | 2 +- junit/kube-api-test/pom.xml | 2 +- junit/kubernetes-junit-jupiter-autodetected/pom.xml | 2 +- junit/kubernetes-junit-jupiter/pom.xml | 2 +- junit/kubernetes-server-mock/pom.xml | 2 +- junit/mockwebserver/pom.xml | 2 +- junit/openshift-server-mock/pom.xml | 2 +- kubernetes-client-api/pom.xml | 2 +- .../kubernetes-client-init-bc-fips/pom.xml | 2 +- kubernetes-client-deps-compatibility-tests/pom.xml | 2 +- kubernetes-client/pom.xml | 2 +- kubernetes-examples/pom.xml | 2 +- kubernetes-itests/pom.xml | 2 +- .../kubernetes-model-admissionregistration/pom.xml | 2 +- .../kubernetes-model-apiextensions/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-apps/pom.xml | 2 +- .../kubernetes-model-autoscaling/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-batch/pom.xml | 2 +- .../kubernetes-model-certificates/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-common/pom.xml | 2 +- .../kubernetes-model-coordination/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-core/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-discovery/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-events/pom.xml | 2 +- .../kubernetes-model-extensions/pom.xml | 2 +- .../kubernetes-model-flowcontrol/pom.xml | 2 +- .../kubernetes-model-gatewayapi/pom.xml | 2 +- .../kubernetes-model-jsonschema2pojo/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-kustomize/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-metrics/pom.xml | 2 +- .../kubernetes-model-networking/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-node/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-policy/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-rbac/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model-resource/pom.xml | 2 +- .../kubernetes-model-scheduling/pom.xml | 2 +- .../kubernetes-model-storageclass/pom.xml | 2 +- kubernetes-model-generator/kubernetes-model/pom.xml | 2 +- .../openshift-model-clusterautoscaling/pom.xml | 2 +- kubernetes-model-generator/openshift-model-config/pom.xml | 2 +- kubernetes-model-generator/openshift-model-console/pom.xml | 2 +- kubernetes-model-generator/openshift-model-hive/pom.xml | 2 +- kubernetes-model-generator/openshift-model-installer/pom.xml | 2 +- kubernetes-model-generator/openshift-model-machine/pom.xml | 2 +- .../openshift-model-machineconfig/pom.xml | 2 +- .../openshift-model-miscellaneous/pom.xml | 2 +- kubernetes-model-generator/openshift-model-monitoring/pom.xml | 2 +- kubernetes-model-generator/openshift-model-operator/pom.xml | 2 +- .../openshift-model-operatorhub/pom.xml | 2 +- .../openshift-model-storageversionmigrator/pom.xml | 2 +- kubernetes-model-generator/openshift-model-tuned/pom.xml | 2 +- .../openshift-model-whereabouts/pom.xml | 2 +- kubernetes-model-generator/openshift-model/pom.xml | 2 +- kubernetes-model-generator/pom.xml | 2 +- kubernetes-tests/pom.xml | 2 +- log4j/pom.xml | 2 +- openshift-client-api/pom.xml | 2 +- openshift-client/pom.xml | 2 +- platforms/karaf/features/pom.xml | 2 +- platforms/karaf/itests/pom.xml | 2 +- platforms/karaf/pom.xml | 2 +- platforms/pom.xml | 2 +- pom.xml | 4 ++-- uberjar/pom.xml | 2 +- 158 files changed, 159 insertions(+), 158 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 99dad3e0040..478448c401b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -48,7 +48,7 @@ body: description: Fabric8 Kubernetes Client version (can be found in pom.xml dependency or build.gradle implementation section) options: - "SNAPSHOT" - - "6.13.3" + - "6.13.4" - "6.12.1" - "6.11.0" - "6.10.0" diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a6e41f4e2d..1f359b51a57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ #### Bugs * Fix #6247: Support for proxy authentication from proxy URL user info * Fix #6342: UnmatchedFieldTypeModule prevents certain jackson features from working +* Fix #6350: Allowing authenticated http proxy usage with Jetty, vertx, and JDK for https endpoints * Fix #6354: Prevent deadlock in okhttp AsyncBody.cancel * Fix #6366: Allow Retry-After header to be considered in retries diff --git a/chaos-tests/pom.xml b/chaos-tests/pom.xml index 7d798ab9030..187a6139724 100644 --- a/chaos-tests/pom.xml +++ b/chaos-tests/pom.xml @@ -21,7 +21,7 @@ io.fabric8 kubernetes-client-project - 6.13.3 + 6.13.4 chaos-tests diff --git a/crd-generator/api-v2/pom.xml b/crd-generator/api-v2/pom.xml index 63381979518..f2847ad232a 100644 --- a/crd-generator/api-v2/pom.xml +++ b/crd-generator/api-v2/pom.xml @@ -22,7 +22,7 @@ crd-generator-parent io.fabric8 - 6.13.3 + 6.13.4 4.0.0 diff --git a/crd-generator/api/pom.xml b/crd-generator/api/pom.xml index 65a3a792c41..f117034fd20 100644 --- a/crd-generator/api/pom.xml +++ b/crd-generator/api/pom.xml @@ -22,7 +22,7 @@ crd-generator-parent io.fabric8 - 6.13.3 + 6.13.4 4.0.0 diff --git a/crd-generator/apt/pom.xml b/crd-generator/apt/pom.xml index bdf5294b7fd..e796afff125 100644 --- a/crd-generator/apt/pom.xml +++ b/crd-generator/apt/pom.xml @@ -22,7 +22,7 @@ crd-generator-parent io.fabric8 - 6.13.3 + 6.13.4 4.0.0 diff --git a/crd-generator/pom.xml b/crd-generator/pom.xml index 97c19d27e17..f6c1afb31d6 100644 --- a/crd-generator/pom.xml +++ b/crd-generator/pom.xml @@ -23,7 +23,7 @@ io.fabric8 kubernetes-client-project - 6.13.3 + 6.13.4 crd-generator-parent diff --git a/crd-generator/test-apt/pom.xml b/crd-generator/test-apt/pom.xml index f1497543129..52fd912931d 100644 --- a/crd-generator/test-apt/pom.xml +++ b/crd-generator/test-apt/pom.xml @@ -22,7 +22,7 @@ crd-generator-parent io.fabric8 - 6.13.3 + 6.13.4 4.0.0 diff --git a/crd-generator/test/pom.xml b/crd-generator/test/pom.xml index 2a3ba0cc479..ebfde7bdbfc 100644 --- a/crd-generator/test/pom.xml +++ b/crd-generator/test/pom.xml @@ -22,7 +22,7 @@ crd-generator-parent io.fabric8 - 6.13.3 + 6.13.4 4.0.0 diff --git a/extensions/certmanager/client/pom.xml b/extensions/certmanager/client/pom.xml index 5ee0dfe48c2..04a82f868d2 100644 --- a/extensions/certmanager/client/pom.xml +++ b/extensions/certmanager/client/pom.xml @@ -22,7 +22,7 @@ io.fabric8 certmanager-extension-pom - 6.13.3 + 6.13.4 certmanager-client diff --git a/extensions/certmanager/examples/pom.xml b/extensions/certmanager/examples/pom.xml index 200b9f404f6..0472f8b6ffb 100644 --- a/extensions/certmanager/examples/pom.xml +++ b/extensions/certmanager/examples/pom.xml @@ -22,7 +22,7 @@ io.fabric8 certmanager-extension-pom - 6.13.3 + 6.13.4 certmanager-examples diff --git a/extensions/certmanager/model-v1/pom.xml b/extensions/certmanager/model-v1/pom.xml index 851fcde65a4..e2a27152281 100755 --- a/extensions/certmanager/model-v1/pom.xml +++ b/extensions/certmanager/model-v1/pom.xml @@ -22,7 +22,7 @@ io.fabric8 certmanager-extension-pom - 6.13.3 + 6.13.4 certmanager-model-v1 diff --git a/extensions/certmanager/model-v1alpha2/pom.xml b/extensions/certmanager/model-v1alpha2/pom.xml index cfcb7d8ef83..97d7f208b42 100755 --- a/extensions/certmanager/model-v1alpha2/pom.xml +++ b/extensions/certmanager/model-v1alpha2/pom.xml @@ -22,7 +22,7 @@ io.fabric8 certmanager-extension-pom - 6.13.3 + 6.13.4 certmanager-model-v1alpha2 diff --git a/extensions/certmanager/model-v1alpha3/pom.xml b/extensions/certmanager/model-v1alpha3/pom.xml index 8a2a997a506..5bf23824ed5 100755 --- a/extensions/certmanager/model-v1alpha3/pom.xml +++ b/extensions/certmanager/model-v1alpha3/pom.xml @@ -22,7 +22,7 @@ io.fabric8 certmanager-extension-pom - 6.13.3 + 6.13.4 certmanager-model-v1alpha3 diff --git a/extensions/certmanager/model-v1beta1/pom.xml b/extensions/certmanager/model-v1beta1/pom.xml index 73d82111e63..18e64b9e438 100755 --- a/extensions/certmanager/model-v1beta1/pom.xml +++ b/extensions/certmanager/model-v1beta1/pom.xml @@ -22,7 +22,7 @@ io.fabric8 certmanager-extension-pom - 6.13.3 + 6.13.4 certmanager-model-v1beta1 diff --git a/extensions/certmanager/pom.xml b/extensions/certmanager/pom.xml index 686decc04df..40a56451b20 100644 --- a/extensions/certmanager/pom.xml +++ b/extensions/certmanager/pom.xml @@ -21,7 +21,7 @@ io.fabric8 kubernetes-extensions - 6.13.3 + 6.13.4 certmanager-extension-pom diff --git a/extensions/certmanager/tests/pom.xml b/extensions/certmanager/tests/pom.xml index 0d600a3cc73..3f0a9d795b2 100644 --- a/extensions/certmanager/tests/pom.xml +++ b/extensions/certmanager/tests/pom.xml @@ -22,7 +22,7 @@ io.fabric8 certmanager-extension-pom - 6.13.3 + 6.13.4 certmanager-tests diff --git a/extensions/chaosmesh/client/pom.xml b/extensions/chaosmesh/client/pom.xml index c5704501a14..071dabd925e 100644 --- a/extensions/chaosmesh/client/pom.xml +++ b/extensions/chaosmesh/client/pom.xml @@ -22,7 +22,7 @@ io.fabric8 chaosmesh - 6.13.3 + 6.13.4 chaosmesh-client diff --git a/extensions/chaosmesh/examples/pom.xml b/extensions/chaosmesh/examples/pom.xml index d063e42804a..2b124b88838 100644 --- a/extensions/chaosmesh/examples/pom.xml +++ b/extensions/chaosmesh/examples/pom.xml @@ -22,7 +22,7 @@ io.fabric8 chaosmesh - 6.13.3 + 6.13.4 chaosmesh-examples diff --git a/extensions/chaosmesh/model/pom.xml b/extensions/chaosmesh/model/pom.xml index f3fc20d6d9a..d2eb9c35f34 100755 --- a/extensions/chaosmesh/model/pom.xml +++ b/extensions/chaosmesh/model/pom.xml @@ -22,7 +22,7 @@ io.fabric8 chaosmesh - 6.13.3 + 6.13.4 chaosmesh-model diff --git a/extensions/chaosmesh/pom.xml b/extensions/chaosmesh/pom.xml index 8f81917fa59..2386fc35862 100644 --- a/extensions/chaosmesh/pom.xml +++ b/extensions/chaosmesh/pom.xml @@ -22,7 +22,7 @@ kubernetes-extensions io.fabric8 - 6.13.3 + 6.13.4 chaosmesh diff --git a/extensions/chaosmesh/tests/pom.xml b/extensions/chaosmesh/tests/pom.xml index 15cb75a8c12..bac93a45923 100644 --- a/extensions/chaosmesh/tests/pom.xml +++ b/extensions/chaosmesh/tests/pom.xml @@ -22,7 +22,7 @@ io.fabric8 chaosmesh - 6.13.3 + 6.13.4 chaosmesh-tests diff --git a/extensions/istio/client/pom.xml b/extensions/istio/client/pom.xml index 1b6ea912b29..de7caa37d8b 100755 --- a/extensions/istio/client/pom.xml +++ b/extensions/istio/client/pom.xml @@ -21,7 +21,7 @@ io.fabric8 istio-extension-pom - 6.13.3 + 6.13.4 istio-client diff --git a/extensions/istio/examples/pom.xml b/extensions/istio/examples/pom.xml index fb3c7d50d19..abd13bf804f 100755 --- a/extensions/istio/examples/pom.xml +++ b/extensions/istio/examples/pom.xml @@ -21,7 +21,7 @@ io.fabric8 istio-extension-pom - 6.13.3 + 6.13.4 istio-examples diff --git a/extensions/istio/model-v1alpha3/pom.xml b/extensions/istio/model-v1alpha3/pom.xml index eb20b18fb19..c5826870335 100644 --- a/extensions/istio/model-v1alpha3/pom.xml +++ b/extensions/istio/model-v1alpha3/pom.xml @@ -23,7 +23,7 @@ io.fabric8 istio-extension-pom - 6.13.3 + 6.13.4 istio-model-v1alpha3 diff --git a/extensions/istio/model-v1beta1/pom.xml b/extensions/istio/model-v1beta1/pom.xml index d158a57b7d3..40925589bc8 100644 --- a/extensions/istio/model-v1beta1/pom.xml +++ b/extensions/istio/model-v1beta1/pom.xml @@ -23,7 +23,7 @@ io.fabric8 istio-extension-pom - 6.13.3 + 6.13.4 istio-model-v1beta1 diff --git a/extensions/istio/pom.xml b/extensions/istio/pom.xml index 4ee604a4c2f..306948f18ed 100755 --- a/extensions/istio/pom.xml +++ b/extensions/istio/pom.xml @@ -21,7 +21,7 @@ io.fabric8 kubernetes-extensions - 6.13.3 + 6.13.4 istio-extension-pom diff --git a/extensions/istio/tests/pom.xml b/extensions/istio/tests/pom.xml index 854431cc2bb..8c3a856248c 100644 --- a/extensions/istio/tests/pom.xml +++ b/extensions/istio/tests/pom.xml @@ -21,7 +21,7 @@ io.fabric8 istio-extension-pom - 6.13.3 + 6.13.4 istio-tests diff --git a/extensions/knative/client/pom.xml b/extensions/knative/client/pom.xml index f0c79c92925..470d7dba731 100755 --- a/extensions/knative/client/pom.xml +++ b/extensions/knative/client/pom.xml @@ -21,7 +21,7 @@ io.fabric8 knative-extension-pom - 6.13.3 + 6.13.4 knative-client diff --git a/extensions/knative/examples/pom.xml b/extensions/knative/examples/pom.xml index 737fca9d712..dee0a0f3fee 100755 --- a/extensions/knative/examples/pom.xml +++ b/extensions/knative/examples/pom.xml @@ -21,7 +21,7 @@ io.fabric8 knative-extension-pom - 6.13.3 + 6.13.4 knative-examples diff --git a/extensions/knative/model/pom.xml b/extensions/knative/model/pom.xml index e2fae752ca0..a557fdd3f7d 100644 --- a/extensions/knative/model/pom.xml +++ b/extensions/knative/model/pom.xml @@ -23,7 +23,7 @@ io.fabric8 knative-extension-pom - 6.13.3 + 6.13.4 knative-model diff --git a/extensions/knative/pom.xml b/extensions/knative/pom.xml index 03e316f1b11..016a9a8d938 100755 --- a/extensions/knative/pom.xml +++ b/extensions/knative/pom.xml @@ -21,7 +21,7 @@ io.fabric8 kubernetes-extensions - 6.13.3 + 6.13.4 knative-extension-pom diff --git a/extensions/knative/tests/pom.xml b/extensions/knative/tests/pom.xml index ce6f15207d9..4ff0f4028e2 100644 --- a/extensions/knative/tests/pom.xml +++ b/extensions/knative/tests/pom.xml @@ -21,7 +21,7 @@ io.fabric8 knative-extension-pom - 6.13.3 + 6.13.4 knative-tests diff --git a/extensions/open-cluster-management/client/pom.xml b/extensions/open-cluster-management/client/pom.xml index 3a2315b3da3..f6d7767c64e 100644 --- a/extensions/open-cluster-management/client/pom.xml +++ b/extensions/open-cluster-management/client/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-client diff --git a/extensions/open-cluster-management/examples/pom.xml b/extensions/open-cluster-management/examples/pom.xml index 67f257c35d0..17bd7186c3b 100644 --- a/extensions/open-cluster-management/examples/pom.xml +++ b/extensions/open-cluster-management/examples/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 openclustermanagement-examples diff --git a/extensions/open-cluster-management/model-agent/pom.xml b/extensions/open-cluster-management/model-agent/pom.xml index 4606086f26d..8b626d31c3d 100755 --- a/extensions/open-cluster-management/model-agent/pom.xml +++ b/extensions/open-cluster-management/model-agent/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-agent-model diff --git a/extensions/open-cluster-management/model-apps/pom.xml b/extensions/open-cluster-management/model-apps/pom.xml index 65c90d3d781..07abbe0ae48 100755 --- a/extensions/open-cluster-management/model-apps/pom.xml +++ b/extensions/open-cluster-management/model-apps/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-apps-model diff --git a/extensions/open-cluster-management/model-cluster/pom.xml b/extensions/open-cluster-management/model-cluster/pom.xml index 3d36253ba72..bb8205b55ea 100755 --- a/extensions/open-cluster-management/model-cluster/pom.xml +++ b/extensions/open-cluster-management/model-cluster/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-cluster-model diff --git a/extensions/open-cluster-management/model-discovery/pom.xml b/extensions/open-cluster-management/model-discovery/pom.xml index fc6d97bf736..d3bf7a92882 100755 --- a/extensions/open-cluster-management/model-discovery/pom.xml +++ b/extensions/open-cluster-management/model-discovery/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-discovery-model diff --git a/extensions/open-cluster-management/model-observability/pom.xml b/extensions/open-cluster-management/model-observability/pom.xml index a8c97b25c0d..14a28d7970f 100755 --- a/extensions/open-cluster-management/model-observability/pom.xml +++ b/extensions/open-cluster-management/model-observability/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-observability-model diff --git a/extensions/open-cluster-management/model-operator/pom.xml b/extensions/open-cluster-management/model-operator/pom.xml index ab125a15662..a21cd440062 100755 --- a/extensions/open-cluster-management/model-operator/pom.xml +++ b/extensions/open-cluster-management/model-operator/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-operator-model diff --git a/extensions/open-cluster-management/model-placementruleapps/pom.xml b/extensions/open-cluster-management/model-placementruleapps/pom.xml index 3c508b795c1..7e5a45f8874 100755 --- a/extensions/open-cluster-management/model-placementruleapps/pom.xml +++ b/extensions/open-cluster-management/model-placementruleapps/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-placementruleapps-model diff --git a/extensions/open-cluster-management/model-policy/pom.xml b/extensions/open-cluster-management/model-policy/pom.xml index 8bd4983ccbd..d8db44fedeb 100755 --- a/extensions/open-cluster-management/model-policy/pom.xml +++ b/extensions/open-cluster-management/model-policy/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-policy-model diff --git a/extensions/open-cluster-management/model-search/pom.xml b/extensions/open-cluster-management/model-search/pom.xml index 36ff2dd211d..5129931053b 100755 --- a/extensions/open-cluster-management/model-search/pom.xml +++ b/extensions/open-cluster-management/model-search/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-search-model diff --git a/extensions/open-cluster-management/pom.xml b/extensions/open-cluster-management/pom.xml index d1caae8145d..c6c5920ea4d 100644 --- a/extensions/open-cluster-management/pom.xml +++ b/extensions/open-cluster-management/pom.xml @@ -22,7 +22,7 @@ kubernetes-extensions io.fabric8 - 6.13.3 + 6.13.4 open-cluster-management diff --git a/extensions/open-cluster-management/tests/pom.xml b/extensions/open-cluster-management/tests/pom.xml index 8018718d07f..c88917d7cd3 100644 --- a/extensions/open-cluster-management/tests/pom.xml +++ b/extensions/open-cluster-management/tests/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-cluster-management - 6.13.3 + 6.13.4 open-cluster-management-tests diff --git a/extensions/open-virtual-networking/client/pom.xml b/extensions/open-virtual-networking/client/pom.xml index 27ea6fcca5a..0118ed28beb 100644 --- a/extensions/open-virtual-networking/client/pom.xml +++ b/extensions/open-virtual-networking/client/pom.xml @@ -23,7 +23,7 @@ io.fabric8 kubernetes-client-project - 6.13.3 + 6.13.4 ../../../pom.xml diff --git a/extensions/open-virtual-networking/model-v1/pom.xml b/extensions/open-virtual-networking/model-v1/pom.xml index 9f8af668474..e97e50f18a2 100755 --- a/extensions/open-virtual-networking/model-v1/pom.xml +++ b/extensions/open-virtual-networking/model-v1/pom.xml @@ -22,7 +22,7 @@ io.fabric8 open-virtual-networking - 6.13.3 + 6.13.4 open-virtual-networking-model-v1 diff --git a/extensions/open-virtual-networking/pom.xml b/extensions/open-virtual-networking/pom.xml index 89c052bccb8..4061ea05fd3 100644 --- a/extensions/open-virtual-networking/pom.xml +++ b/extensions/open-virtual-networking/pom.xml @@ -22,7 +22,7 @@ kubernetes-extensions io.fabric8 - 6.13.3 + 6.13.4 open-virtual-networking diff --git a/extensions/open-virtual-networking/tests/pom.xml b/extensions/open-virtual-networking/tests/pom.xml index 9eb7d2e0052..cf41ba3b2b0 100644 --- a/extensions/open-virtual-networking/tests/pom.xml +++ b/extensions/open-virtual-networking/tests/pom.xml @@ -23,7 +23,7 @@ io.fabric8 kubernetes-client-project - 6.13.3 + 6.13.4 ../../../pom.xml open-virtual-networking-tests diff --git a/extensions/pom.xml b/extensions/pom.xml index c9a3ddaadbc..96475ed1178 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -21,7 +21,7 @@ kubernetes-client-project io.fabric8 - 6.13.3 + 6.13.4 kubernetes-extensions diff --git a/extensions/service-catalog/client/pom.xml b/extensions/service-catalog/client/pom.xml index b94ef95fdb3..404d2098c2a 100644 --- a/extensions/service-catalog/client/pom.xml +++ b/extensions/service-catalog/client/pom.xml @@ -21,7 +21,7 @@ io.fabric8 service-catalog - 6.13.3 + 6.13.4 servicecatalog-client diff --git a/extensions/service-catalog/examples/pom.xml b/extensions/service-catalog/examples/pom.xml index abf728680ec..7b2c8c01818 100644 --- a/extensions/service-catalog/examples/pom.xml +++ b/extensions/service-catalog/examples/pom.xml @@ -21,7 +21,7 @@ io.fabric8 service-catalog - 6.13.3 + 6.13.4 service-catalog-examples diff --git a/extensions/service-catalog/model/pom.xml b/extensions/service-catalog/model/pom.xml index ba79556f529..505c955dc47 100755 --- a/extensions/service-catalog/model/pom.xml +++ b/extensions/service-catalog/model/pom.xml @@ -21,7 +21,7 @@ io.fabric8 service-catalog - 6.13.3 + 6.13.4 servicecatalog-model diff --git a/extensions/service-catalog/pom.xml b/extensions/service-catalog/pom.xml index f556987f18c..8606e73e3f2 100644 --- a/extensions/service-catalog/pom.xml +++ b/extensions/service-catalog/pom.xml @@ -21,7 +21,7 @@ kubernetes-extensions io.fabric8 - 6.13.3 + 6.13.4 service-catalog diff --git a/extensions/service-catalog/tests/pom.xml b/extensions/service-catalog/tests/pom.xml index 8cc48b5d007..b3807d8fe19 100644 --- a/extensions/service-catalog/tests/pom.xml +++ b/extensions/service-catalog/tests/pom.xml @@ -21,7 +21,7 @@ io.fabric8 service-catalog - 6.13.3 + 6.13.4 servicecatalog-tests diff --git a/extensions/tekton/client/pom.xml b/extensions/tekton/client/pom.xml index eec371e12a5..59eaf99c499 100644 --- a/extensions/tekton/client/pom.xml +++ b/extensions/tekton/client/pom.xml @@ -21,7 +21,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-client diff --git a/extensions/tekton/examples/pom.xml b/extensions/tekton/examples/pom.xml index d48458bcd00..96f147a7d2e 100755 --- a/extensions/tekton/examples/pom.xml +++ b/extensions/tekton/examples/pom.xml @@ -21,7 +21,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-examples diff --git a/extensions/tekton/model-triggers-v1alpha1/pom.xml b/extensions/tekton/model-triggers-v1alpha1/pom.xml index 9c908a72ec8..f710570f526 100644 --- a/extensions/tekton/model-triggers-v1alpha1/pom.xml +++ b/extensions/tekton/model-triggers-v1alpha1/pom.xml @@ -23,7 +23,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-model-triggers-v1alpha1 diff --git a/extensions/tekton/model-triggers-v1beta1/pom.xml b/extensions/tekton/model-triggers-v1beta1/pom.xml index 34cd78c5fcb..ae87e2fa8d9 100644 --- a/extensions/tekton/model-triggers-v1beta1/pom.xml +++ b/extensions/tekton/model-triggers-v1beta1/pom.xml @@ -23,7 +23,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-model-triggers-v1beta1 diff --git a/extensions/tekton/model-v1/pom.xml b/extensions/tekton/model-v1/pom.xml index ee3482149ff..dcb7a587d72 100644 --- a/extensions/tekton/model-v1/pom.xml +++ b/extensions/tekton/model-v1/pom.xml @@ -21,7 +21,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-model-v1 diff --git a/extensions/tekton/model-v1alpha1/pom.xml b/extensions/tekton/model-v1alpha1/pom.xml index b85db6dd8bd..b4ffd02fc91 100644 --- a/extensions/tekton/model-v1alpha1/pom.xml +++ b/extensions/tekton/model-v1alpha1/pom.xml @@ -21,7 +21,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-model-v1alpha1 diff --git a/extensions/tekton/model-v1beta1/pom.xml b/extensions/tekton/model-v1beta1/pom.xml index ff3bca65b96..eee72e50b0d 100644 --- a/extensions/tekton/model-v1beta1/pom.xml +++ b/extensions/tekton/model-v1beta1/pom.xml @@ -23,7 +23,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-model-v1beta1 diff --git a/extensions/tekton/pom.xml b/extensions/tekton/pom.xml index e5bb7d9ff3f..cc43d180a9d 100755 --- a/extensions/tekton/pom.xml +++ b/extensions/tekton/pom.xml @@ -21,7 +21,7 @@ io.fabric8 kubernetes-extensions - 6.13.3 + 6.13.4 tekton-extension-pom diff --git a/extensions/tekton/tests/pom.xml b/extensions/tekton/tests/pom.xml index 1726d96c149..95cd59ad29d 100644 --- a/extensions/tekton/tests/pom.xml +++ b/extensions/tekton/tests/pom.xml @@ -21,7 +21,7 @@ io.fabric8 tekton-extension-pom - 6.13.3 + 6.13.4 tekton-tests diff --git a/extensions/verticalpodautoscaler/client/pom.xml b/extensions/verticalpodautoscaler/client/pom.xml index fdc3cb4f0d0..205464e7359 100644 --- a/extensions/verticalpodautoscaler/client/pom.xml +++ b/extensions/verticalpodautoscaler/client/pom.xml @@ -22,7 +22,7 @@ io.fabric8 verticalpodautoscaler-extension-pom - 6.13.3 + 6.13.4 verticalpodautoscaler-client diff --git a/extensions/verticalpodautoscaler/examples/pom.xml b/extensions/verticalpodautoscaler/examples/pom.xml index 689413b256c..45073ae5d21 100644 --- a/extensions/verticalpodautoscaler/examples/pom.xml +++ b/extensions/verticalpodautoscaler/examples/pom.xml @@ -22,7 +22,7 @@ io.fabric8 verticalpodautoscaler-extension-pom - 6.13.3 + 6.13.4 verticalpodautoscaler-examples diff --git a/extensions/verticalpodautoscaler/model-v1/pom.xml b/extensions/verticalpodautoscaler/model-v1/pom.xml index 8f51492d311..45062228ea8 100755 --- a/extensions/verticalpodautoscaler/model-v1/pom.xml +++ b/extensions/verticalpodautoscaler/model-v1/pom.xml @@ -22,7 +22,7 @@ io.fabric8 verticalpodautoscaler-extension-pom - 6.13.3 + 6.13.4 verticalpodautoscaler-model-v1 diff --git a/extensions/verticalpodautoscaler/pom.xml b/extensions/verticalpodautoscaler/pom.xml index acbee73cccc..5ab779803de 100644 --- a/extensions/verticalpodautoscaler/pom.xml +++ b/extensions/verticalpodautoscaler/pom.xml @@ -21,7 +21,7 @@ io.fabric8 kubernetes-extensions - 6.13.3 + 6.13.4 verticalpodautoscaler-extension-pom diff --git a/extensions/verticalpodautoscaler/tests/pom.xml b/extensions/verticalpodautoscaler/tests/pom.xml index b772d546a22..a5be3a9baa0 100644 --- a/extensions/verticalpodautoscaler/tests/pom.xml +++ b/extensions/verticalpodautoscaler/tests/pom.xml @@ -22,7 +22,7 @@ io.fabric8 verticalpodautoscaler-extension-pom - 6.13.3 + 6.13.4 verticalpodautoscaler-tests diff --git a/extensions/volcano/client/pom.xml b/extensions/volcano/client/pom.xml index 80c7b2bacc5..af3d0b2e76d 100644 --- a/extensions/volcano/client/pom.xml +++ b/extensions/volcano/client/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volcano-extension-pom - 6.13.3 + 6.13.4 volcano-client diff --git a/extensions/volcano/examples/pom.xml b/extensions/volcano/examples/pom.xml index cb9e8c85797..d5fca04c46a 100644 --- a/extensions/volcano/examples/pom.xml +++ b/extensions/volcano/examples/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volcano-extension-pom - 6.13.3 + 6.13.4 volcano-examples diff --git a/extensions/volcano/model-v1beta1/pom.xml b/extensions/volcano/model-v1beta1/pom.xml index f20f4b3d4cd..8b8557d0af5 100644 --- a/extensions/volcano/model-v1beta1/pom.xml +++ b/extensions/volcano/model-v1beta1/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volcano-extension-pom - 6.13.3 + 6.13.4 volcano-model-v1beta1 diff --git a/extensions/volcano/pom.xml b/extensions/volcano/pom.xml index 424a5a4070c..e5cda4f5d6d 100644 --- a/extensions/volcano/pom.xml +++ b/extensions/volcano/pom.xml @@ -21,7 +21,7 @@ kubernetes-extensions io.fabric8 - 6.13.3 + 6.13.4 volcano-extension-pom diff --git a/extensions/volcano/tests/pom.xml b/extensions/volcano/tests/pom.xml index 048d1466600..0574b0c2346 100644 --- a/extensions/volcano/tests/pom.xml +++ b/extensions/volcano/tests/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volcano-extension-pom - 6.13.3 + 6.13.4 volcano-tests diff --git a/extensions/volumesnapshot/client/pom.xml b/extensions/volumesnapshot/client/pom.xml index 41e61f06b7d..caeb8452dce 100644 --- a/extensions/volumesnapshot/client/pom.xml +++ b/extensions/volumesnapshot/client/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volumesnapshot - 6.13.3 + 6.13.4 volumesnapshot-client diff --git a/extensions/volumesnapshot/examples/pom.xml b/extensions/volumesnapshot/examples/pom.xml index c5a5a679ce9..fc9a394f4d6 100644 --- a/extensions/volumesnapshot/examples/pom.xml +++ b/extensions/volumesnapshot/examples/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volumesnapshot - 6.13.3 + 6.13.4 volumesnapshot-examples diff --git a/extensions/volumesnapshot/model/pom.xml b/extensions/volumesnapshot/model/pom.xml index 6cd8aeffa15..bf2982f4a59 100755 --- a/extensions/volumesnapshot/model/pom.xml +++ b/extensions/volumesnapshot/model/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volumesnapshot - 6.13.3 + 6.13.4 volumesnapshot-model diff --git a/extensions/volumesnapshot/pom.xml b/extensions/volumesnapshot/pom.xml index a53d4843f95..57bf2ebc7c2 100644 --- a/extensions/volumesnapshot/pom.xml +++ b/extensions/volumesnapshot/pom.xml @@ -22,7 +22,7 @@ kubernetes-extensions io.fabric8 - 6.13.3 + 6.13.4 volumesnapshot diff --git a/extensions/volumesnapshot/tests/pom.xml b/extensions/volumesnapshot/tests/pom.xml index 11a5deacfc0..70dc46dde47 100644 --- a/extensions/volumesnapshot/tests/pom.xml +++ b/extensions/volumesnapshot/tests/pom.xml @@ -22,7 +22,7 @@ io.fabric8 volumesnapshot - 6.13.3 + 6.13.4 volumesnapshot-tests diff --git a/generator-annotations/pom.xml b/generator-annotations/pom.xml index 96b759734d2..c60dd375812 100644 --- a/generator-annotations/pom.xml +++ b/generator-annotations/pom.xml @@ -23,7 +23,7 @@ io.fabric8 kubernetes-client-project - 6.13.3 + 6.13.4 generator-annotations diff --git a/httpclient-jdk/pom.xml b/httpclient-jdk/pom.xml index 6e629d05e95..d4628a4b8cc 100644 --- a/httpclient-jdk/pom.xml +++ b/httpclient-jdk/pom.xml @@ -21,7 +21,7 @@ kubernetes-client-project io.fabric8 - 6.13.3 + 6.13.4 kubernetes-httpclient-jdk diff --git a/httpclient-jetty/pom.xml b/httpclient-jetty/pom.xml index 31990ca4964..0e7311ecf33 100644 --- a/httpclient-jetty/pom.xml +++ b/httpclient-jetty/pom.xml @@ -21,7 +21,7 @@ kubernetes-client-project io.fabric8 - 6.13.3 + 6.13.4 kubernetes-httpclient-jetty diff --git a/httpclient-okhttp/pom.xml b/httpclient-okhttp/pom.xml index 57a7513bfbf..3f47177fda0 100644 --- a/httpclient-okhttp/pom.xml +++ b/httpclient-okhttp/pom.xml @@ -21,7 +21,7 @@ kubernetes-client-project io.fabric8 - 6.13.3 + 6.13.4 kubernetes-httpclient-okhttp diff --git a/httpclient-tests/pom.xml b/httpclient-tests/pom.xml index 630918bf674..ce46a3588a8 100644 --- a/httpclient-tests/pom.xml +++ b/httpclient-tests/pom.xml @@ -21,7 +21,7 @@ kubernetes-client-project io.fabric8 - 6.13.3 + 6.13.4 kubernetes-httpclient-tests diff --git a/httpclient-vertx/pom.xml b/httpclient-vertx/pom.xml index 401c4d7b879..82d2eaff564 100644 --- a/httpclient-vertx/pom.xml +++ b/httpclient-vertx/pom.xml @@ -21,7 +21,7 @@ kubernetes-client-project io.fabric8 - 6.13.3 + 6.13.4 kubernetes-httpclient-vertx diff --git a/java-generator/benchmark/pom.xml b/java-generator/benchmark/pom.xml index a65f7fb1cb6..a63a58f9414 100644 --- a/java-generator/benchmark/pom.xml +++ b/java-generator/benchmark/pom.xml @@ -22,7 +22,7 @@ java-generator-parent io.fabric8 - 6.13.3 + 6.13.4 java-generator-benchmark diff --git a/java-generator/cli/pom.xml b/java-generator/cli/pom.xml index 6894d56e3aa..de6103ecab5 100644 --- a/java-generator/cli/pom.xml +++ b/java-generator/cli/pom.xml @@ -22,7 +22,7 @@ java-generator-parent io.fabric8 - 6.13.3 + 6.13.4 4.0.0 diff --git a/java-generator/core/pom.xml b/java-generator/core/pom.xml index 0ba643aa846..d1eaec50c49 100644 --- a/java-generator/core/pom.xml +++ b/java-generator/core/pom.xml @@ -22,7 +22,7 @@ java-generator-parent io.fabric8 - 6.13.3 + 6.13.4 4.0.0 diff --git a/java-generator/gradle-plugin/pom.xml b/java-generator/gradle-plugin/pom.xml index 503a9326098..b2697189bb5 100644 --- a/java-generator/gradle-plugin/pom.xml +++ b/java-generator/gradle-plugin/pom.xml @@ -23,7 +23,7 @@ java-generator-parent io.fabric8 - 6.13.3 + 6.13.4