Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Commit

Permalink
ISSUE 158 - BugFix Health Check when provided TopicARN
Browse files Browse the repository at this point in the history
  • Loading branch information
Aryelmr committed Jan 15, 2024
1 parent 7a5a632 commit a991587
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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();
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 {
Expand All @@ -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));

Expand All @@ -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));

Expand All @@ -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<String, BindingProperties> 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);
Expand All @@ -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));

Expand Down

0 comments on commit a991587

Please sign in to comment.