From 1bd14652d8b69634aa19422e617878b8282b1752 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 11 Oct 2023 09:12:26 +0200 Subject: [PATCH] Apply Wavefront token type to auto-configured WavefrontSender Closes gh-37165 --- .../WavefrontPropertiesConfigAdapter.java | 12 +--- .../wavefront/WavefrontProperties.java | 21 ++++++- .../WavefrontSenderConfiguration.java | 3 +- .../wavefront/WavefrontPropertiesTests.java | 57 +++++++++++++++---- .../WavefrontSenderConfigurationTests.java | 49 ++++++++++++++++ 5 files changed, 119 insertions(+), 23 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontPropertiesConfigAdapter.java index 1f64342b16..bd898ddad0 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontPropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontPropertiesConfigAdapter.java @@ -22,7 +22,6 @@ import io.micrometer.wavefront.WavefrontConfig; import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryPropertiesConfigAdapter; import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties; import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.Metrics.Export; -import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.TokenType; /** * Adapter to convert {@link WavefrontProperties} to a {@link WavefrontConfig}. @@ -88,16 +87,7 @@ public class WavefrontPropertiesConfigAdapter @Override public Type apiTokenType() { - TokenType apiTokenType = this.properties.getApiTokenType(); - if (apiTokenType == null) { - return WavefrontConfig.super.apiTokenType(); - } - return switch (apiTokenType) { - case NO_TOKEN -> Type.NO_TOKEN; - case WAVEFRONT_API_TOKEN -> Type.WAVEFRONT_API_TOKEN; - case CSP_API_TOKEN -> Type.CSP_API_TOKEN; - case CSP_CLIENT_CREDENTIALS -> Type.CSP_CLIENT_CREDENTIALS; - }; + return this.properties.getWavefrontApiTokenType(); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java index 77fbd189a6..ce313c3360 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java @@ -25,6 +25,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import com.wavefront.sdk.common.clients.service.token.TokenService.Type; + import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; @@ -137,7 +139,7 @@ public class WavefrontProperties { * @return the API token */ public String getApiTokenOrThrow() { - if (this.apiToken == null && !usesProxy()) { + if (this.apiTokenType != TokenType.NO_TOKEN && this.apiToken == null && !usesProxy()) { throw new InvalidConfigurationPropertyValueException("management.wavefront.api-token", null, "This property is mandatory whenever publishing directly to the Wavefront API"); } @@ -180,6 +182,23 @@ public class WavefrontProperties { this.apiTokenType = apiTokenType; } + /** + * Returns the {@link Type Wavefront token type}. + * @return the Wavefront token type + * @since 3.2.0 + */ + public Type getWavefrontApiTokenType() { + if (this.apiTokenType == null) { + return usesProxy() ? Type.NO_TOKEN : Type.WAVEFRONT_API_TOKEN; + } + return switch (this.apiTokenType) { + case NO_TOKEN -> Type.NO_TOKEN; + case WAVEFRONT_API_TOKEN -> Type.WAVEFRONT_API_TOKEN; + case CSP_API_TOKEN -> Type.CSP_API_TOKEN; + case CSP_CLIENT_CREDENTIALS -> Type.CSP_CLIENT_CREDENTIALS; + }; + } + public static class Application { /** diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java index 4387827221..f7ffa4d069 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java @@ -52,7 +52,8 @@ public class WavefrontSenderConfiguration { @ConditionalOnMissingBean @Conditional(WavefrontTracingOrMetricsCondition.class) public WavefrontSender wavefrontSender(WavefrontProperties properties) { - Builder builder = new Builder(properties.getEffectiveUri().toString(), properties.getApiTokenOrThrow()); + Builder builder = new Builder(properties.getEffectiveUri().toString(), properties.getWavefrontApiTokenType(), + properties.getApiTokenOrThrow()); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); WavefrontProperties.Sender sender = properties.getSender(); map.from(sender.getMaxQueueSize()).to(builder::maxQueueSize); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontPropertiesTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontPropertiesTests.java index 02d1ce3b77..8eacdc9e29 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontPropertiesTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontPropertiesTests.java @@ -18,8 +18,12 @@ package org.springframework.boot.actuate.autoconfigure.wavefront; import java.net.URI; +import com.wavefront.sdk.common.clients.service.token.TokenService.Type; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.springframework.boot.actuate.autoconfigure.wavefront.WavefrontProperties.TokenType; import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; import static org.assertj.core.api.Assertions.assertThat; @@ -34,21 +38,54 @@ class WavefrontPropertiesTests { @Test void apiTokenIsOptionalWhenUsingProxy() { - WavefrontProperties sut = new WavefrontProperties(); - sut.setUri(URI.create("proxy://localhost:2878")); - sut.setApiToken(null); - assertThat(sut.getApiTokenOrThrow()).isNull(); - assertThat(sut.getEffectiveUri()).isEqualTo(URI.create("http://localhost:2878")); + WavefrontProperties properties = new WavefrontProperties(); + properties.setUri(URI.create("proxy://localhost:2878")); + properties.setApiToken(null); + assertThat(properties.getApiTokenOrThrow()).isNull(); + assertThat(properties.getEffectiveUri()).isEqualTo(URI.create("http://localhost:2878")); } @Test void apiTokenIsMandatoryWhenNotUsingProxy() { - WavefrontProperties sut = new WavefrontProperties(); - sut.setUri(URI.create("http://localhost:2878")); - sut.setApiToken(null); - assertThat(sut.getEffectiveUri()).isEqualTo(URI.create("http://localhost:2878")); - assertThatThrownBy(sut::getApiTokenOrThrow).isInstanceOf(InvalidConfigurationPropertyValueException.class) + WavefrontProperties properties = new WavefrontProperties(); + properties.setUri(URI.create("http://localhost:2878")); + properties.setApiToken(null); + assertThat(properties.getEffectiveUri()).isEqualTo(URI.create("http://localhost:2878")); + assertThatThrownBy(properties::getApiTokenOrThrow) + .isInstanceOf(InvalidConfigurationPropertyValueException.class) .hasMessageContaining("management.wavefront.api-token"); } + @Test + void shouldNotFailIfTokenTypeIsSetToNoToken() { + WavefrontProperties properties = new WavefrontProperties(); + properties.setUri(URI.create("http://localhost:2878")); + properties.setApiTokenType(TokenType.NO_TOKEN); + properties.setApiToken(null); + assertThat(properties.getApiTokenOrThrow()).isNull(); + } + + @Test + void wavefrontApiTokenTypeWhenUsingProxy() { + WavefrontProperties properties = new WavefrontProperties(); + properties.setUri(URI.create("proxy://localhost:2878")); + assertThat(properties.getWavefrontApiTokenType()).isEqualTo(Type.NO_TOKEN); + } + + @Test + void wavefrontApiTokenTypeWhenNotUsingProxy() { + WavefrontProperties properties = new WavefrontProperties(); + properties.setUri(URI.create("http://localhost:2878")); + assertThat(properties.getWavefrontApiTokenType()).isEqualTo(Type.WAVEFRONT_API_TOKEN); + } + + @ParameterizedTest + @EnumSource(TokenType.class) + void wavefrontApiTokenMapping(TokenType from) { + WavefrontProperties properties = new WavefrontProperties(); + properties.setApiTokenType(from); + Type expected = Type.valueOf(from.name()); + assertThat(properties.getWavefrontApiTokenType()).isEqualTo(expected); + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfigurationTests.java index 367adebb5c..6091baf221 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfigurationTests.java @@ -19,6 +19,9 @@ package org.springframework.boot.actuate.autoconfigure.wavefront; import java.util.concurrent.LinkedBlockingQueue; import com.wavefront.sdk.common.WavefrontSender; +import com.wavefront.sdk.common.clients.service.token.CSPTokenService; +import com.wavefront.sdk.common.clients.service.token.NoopProxyTokenService; +import com.wavefront.sdk.common.clients.service.token.WavefrontTokenService; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; @@ -27,6 +30,7 @@ import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.as; import static org.assertj.core.api.Assertions.assertThat; @@ -118,6 +122,51 @@ class WavefrontSenderConfigurationTests { .run((context) -> assertThat(context).hasSingleBean(WavefrontSender.class).hasBean("customSender")); } + @Test + void shouldApplyTokenTypeWavefrontApiToken() { + this.contextRunner + .withPropertyValues("management.wavefront.api-token-type=WAVEFRONT_API_TOKEN", + "management.wavefront.api-token=abcde") + .run((context) -> { + WavefrontSender sender = context.getBean(WavefrontSender.class); + Object tokenService = ReflectionTestUtils.getField(sender, "tokenService"); + assertThat(tokenService).isInstanceOf(WavefrontTokenService.class); + }); + } + + @Test + void shouldApplyTokenTypeCspApiToken() { + this.contextRunner + .withPropertyValues("management.wavefront.api-token-type=CSP_API_TOKEN", + "management.wavefront.api-token=abcde") + .run((context) -> { + WavefrontSender sender = context.getBean(WavefrontSender.class); + Object tokenService = ReflectionTestUtils.getField(sender, "tokenService"); + assertThat(tokenService).isInstanceOf(CSPTokenService.class); + }); + } + + @Test + void shouldApplyTokenTypeCspClientCredentials() { + this.contextRunner + .withPropertyValues("management.wavefront.api-token-type=CSP_CLIENT_CREDENTIALS", + "management.wavefront.api-token=clientid=cid,clientsecret=csec") + .run((context) -> { + WavefrontSender sender = context.getBean(WavefrontSender.class); + Object tokenService = ReflectionTestUtils.getField(sender, "tokenService"); + assertThat(tokenService).isInstanceOf(CSPTokenService.class); + }); + } + + @Test + void shouldApplyTokenTypeNoToken() { + this.contextRunner.withPropertyValues("management.wavefront.api-token-type=NO_TOKEN").run((context) -> { + WavefrontSender sender = context.getBean(WavefrontSender.class); + Object tokenService = ReflectionTestUtils.getField(sender, "tokenService"); + assertThat(tokenService).isInstanceOf(NoopProxyTokenService.class); + }); + } + @Configuration(proxyBeanMethods = false) static class CustomSenderConfiguration {