From a9915879466f90ec601837f9edf3b6cb13706d7a Mon Sep 17 00:00:00 2001 From: Aryel Maia Date: Mon, 15 Jan 2024 14:31:36 -0500 Subject: [PATCH] ISSUE 158 - BugFix Health Check when provided TopicARN --- .../sns/health/SnsBinderHealthIndicator.java | 9 ++- .../health/SnsBinderHealthIndicatorTest.java | 63 ++++++++++++------- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/main/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicator.java b/src/main/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicator.java index 84541d0..7d646dc 100644 --- a/src/main/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicator.java +++ b/src/main/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicator.java @@ -16,6 +16,7 @@ public class SnsBinderHealthIndicator extends AbstractHealthIndicator { private final SnsMessageHandlerBinder snsMessageHandlerBinder; private final BindingServiceProperties bindingServiceProperties; + private static final String ARN_PREFIX = "arn"; public SnsBinderHealthIndicator(final SnsMessageHandlerBinder snsMessageHandlerBinder, final BindingServiceProperties bindingServiceProperties) { Assert.notNull(snsMessageHandlerBinder, "SnsMessageHandlerBinder must not be null"); @@ -31,13 +32,14 @@ protected void doHealthCheck(Health.Builder builder) { .thenApply(List::stream) .join() .map(Topic::topicArn) - .map(topicArn -> topicArn.substring(topicArn.lastIndexOf(':') + 1)) + .map(SnsBinderHealthIndicator::extractTopicNameFromTopicArn) .collect(Collectors.toSet()); var availableDeclaredTopics = bindingServiceProperties.getBindings().values().stream() .filter(bindingProperties -> "sns".equalsIgnoreCase(bindingProperties.getBinder())) .map(BindingProperties::getDestination) - .allMatch(declaredTopic -> availableTopics.contains(declaredTopic)); + .map(SnsBinderHealthIndicator::extractTopicNameFromTopicArn) + .allMatch(availableTopics::contains); if (availableDeclaredTopics) { builder.up(); @@ -46,4 +48,7 @@ protected void doHealthCheck(Health.Builder builder) { } } + public static String extractTopicNameFromTopicArn(String topicArn){ + return topicArn.startsWith(ARN_PREFIX) ? topicArn.substring(topicArn.lastIndexOf(':') + 1) : topicArn; + } } diff --git a/src/test/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicatorTest.java b/src/test/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicatorTest.java index 65580b4..7752511 100644 --- a/src/test/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicatorTest.java +++ b/src/test/java/de/idealo/spring/stream/binder/sns/health/SnsBinderHealthIndicatorTest.java @@ -1,16 +1,6 @@ package de.idealo.spring.stream.binder.sns.health; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.when; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - +import de.idealo.spring.stream.binder.sns.SnsMessageHandlerBinder; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -21,13 +11,20 @@ import org.springframework.boot.actuate.health.Status; import org.springframework.cloud.stream.config.BindingProperties; import org.springframework.cloud.stream.config.BindingServiceProperties; - import software.amazon.awssdk.services.sns.SnsAsyncClient; import software.amazon.awssdk.services.sns.model.AuthorizationErrorException; import software.amazon.awssdk.services.sns.model.ListTopicsResponse; import software.amazon.awssdk.services.sns.model.Topic; -import de.idealo.spring.stream.binder.sns.SnsMessageHandlerBinder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class SnsBinderHealthIndicatorTest { @@ -48,12 +45,30 @@ class SnsBinderHealthIndicatorTest { void setUp() { lenient().when(snsMessageHandlerBinder.getAmazonSNS()).thenReturn(amazonSNS); } + private final String ARN_PATH_PREFIX = "arn:partition:service:region:account-id:"; + private final String TOPIC_NAME = "topicName"; + private final String TOPIC_ARN = ARN_PATH_PREFIX + TOPIC_NAME; + + @Test + void shouldSucceedIfProvidedTopicArnInsteadOfTopicName() { + when(amazonSNS.listTopics()).thenReturn(CompletableFuture.completedFuture(ListTopicsResponse.builder().topics(Topic.builder().topicArn(TOPIC_ARN).build()).build())); + final BindingProperties binderProperties = new BindingProperties(); + binderProperties.setDestination(TOPIC_ARN); + binderProperties.setBinder("sns"); + when(bindingServiceProperties.getBindings()).thenReturn(Collections.singletonMap("doesn't matter", binderProperties)); + + Health.Builder builder = new Health.Builder(); + + healthIndicator.doHealthCheck(builder); + + assertThat(builder.build().getStatus()).isEqualTo(Status.UP); + } @Test void reportsTrueWhenAllTopicsCanBeListed() { - when(amazonSNS.listTopics()).thenReturn(CompletableFuture.completedFuture(ListTopicsResponse.builder().topics(Topic.builder().topicArn("blablabla:somemorebla:topicName").build()).build())); + when(amazonSNS.listTopics()).thenReturn(CompletableFuture.completedFuture(ListTopicsResponse.builder().topics(Topic.builder().topicArn(TOPIC_ARN).build()).build())); final BindingProperties binderProperties = new BindingProperties(); - binderProperties.setDestination("topicName"); + binderProperties.setDestination(TOPIC_NAME); binderProperties.setBinder("sns"); when(bindingServiceProperties.getBindings()).thenReturn(Collections.singletonMap("doesn't matter", binderProperties)); @@ -68,12 +83,12 @@ void reportsTrueWhenAllTopicsCanBeListed() { void reportsTrueWhenMoreTopicsThenDestinationsArePresent() { when(amazonSNS.listTopics()).thenReturn( CompletableFuture.completedFuture(ListTopicsResponse.builder().topics( - Topic.builder().topicArn("blablabla:somemorebla:topicName1").build(), - Topic.builder().topicArn("blablabla:somemorebla:topicName2").build()) + Topic.builder().topicArn(TOPIC_ARN + "1").build(), + Topic.builder().topicArn(TOPIC_ARN + "2").build()) .build()) ); final BindingProperties binderProperties = new BindingProperties(); - binderProperties.setDestination("topicName1"); + binderProperties.setDestination(TOPIC_NAME + "1"); binderProperties.setBinder("sns"); when(bindingServiceProperties.getBindings()).thenReturn(Collections.singletonMap("doesn't matter", binderProperties)); @@ -88,18 +103,18 @@ void reportsTrueWhenMoreTopicsThenDestinationsArePresent() { void filtersOutNonSnsBinders() { when(amazonSNS.listTopics()).thenReturn( CompletableFuture.completedFuture(ListTopicsResponse.builder().topics( - Topic.builder().topicArn("blablabla:somemorebla:topicName1").build(), - Topic.builder().topicArn("blablabla:somemorebla:topicName2").build()) + Topic.builder().topicArn(TOPIC_ARN + "1").build(), + Topic.builder().topicArn(TOPIC_ARN + "2").build()) .build()) ); Map bindings = new HashMap<>(); final BindingProperties binderPropertiesSns = new BindingProperties(); - binderPropertiesSns.setDestination("topicName1"); + binderPropertiesSns.setDestination(TOPIC_NAME + "1"); binderPropertiesSns.setBinder("sns"); bindings.put("doesn't matter", binderPropertiesSns); final BindingProperties binderPropertiesKafka = new BindingProperties(); - binderPropertiesKafka.setDestination("topicName2"); + binderPropertiesKafka.setDestination(TOPIC_NAME + "2"); binderPropertiesKafka.setBinder("kafka"); bindings.put("still doesn't matter", binderPropertiesKafka); when(bindingServiceProperties.getBindings()).thenReturn(bindings); @@ -113,9 +128,9 @@ void filtersOutNonSnsBinders() { @Test void reportsFalseWhenAnExpectedTopicIsNotPresent() { - when(amazonSNS.listTopics()).thenReturn(CompletableFuture.completedFuture(ListTopicsResponse.builder().topics(Topic.builder().topicArn("blablabla:somemorebla:wrongTopicName").build()).build())); + when(amazonSNS.listTopics()).thenReturn(CompletableFuture.completedFuture(ListTopicsResponse.builder().topics(Topic.builder().topicArn(ARN_PATH_PREFIX + "wrongTopicName").build()).build())); final BindingProperties binderProperties = new BindingProperties(); - binderProperties.setDestination("topicName"); + binderProperties.setDestination(TOPIC_NAME); binderProperties.setBinder("sns"); when(bindingServiceProperties.getBindings()).thenReturn(Collections.singletonMap("doesn't matter", binderProperties));