Skip to content

Extend properties for RedisSentinelConfiguration #2861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ public RedisConnectionFactory jedisConnectionFactory() {
* `spring.redis.sentinel.nodes`: Comma delimited list of host:port pairs.
* `spring.redis.sentinel.username`: The username to apply when authenticating with Redis Sentinel (requires Redis 6)
* `spring.redis.sentinel.password`: The password to apply when authenticating with Redis Sentinel
* `spring.redis.sentinel.dataNode.username`: The username to apply when authenticating with Redis Data Node
* `spring.redis.sentinel.dataNode.password`: The password to apply when authenticating with Redis Data Node
* `spring.redis.sentinel.dataNode.database`: The database index to apply when authenticating with Redis Data Node
====

Sometimes, direct interaction with one of the Sentinels is required. Using `RedisConnectionFactory.getSentinelConnection()` or `RedisConnection.getSentinelCommands()` gives you access to the first active Sentinel configured.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
* @author Mark Paluch
* @author Vikas Garg
* @author John Blum
* @author Samuel Klose
* @author Mustapha Zorgati
* @since 1.4
*/
public class RedisSentinelConfiguration implements RedisConfiguration, SentinelConfiguration {
Expand All @@ -49,6 +51,9 @@ public class RedisSentinelConfiguration implements RedisConfiguration, SentinelC
private static final String REDIS_SENTINEL_NODES_CONFIG_PROPERTY = "spring.redis.sentinel.nodes";
private static final String REDIS_SENTINEL_USERNAME_CONFIG_PROPERTY = "spring.redis.sentinel.username";
private static final String REDIS_SENTINEL_PASSWORD_CONFIG_PROPERTY = "spring.redis.sentinel.password";
private static final String REDIS_SENTINEL_DATA_NODE_USERNAME_CONFIG_PROPERTY = "spring.redis.sentinel.dataNode.username";
private static final String REDIS_SENTINEL_DATA_NODE_PASSWORD_CONFIG_PROPERTY = "spring.redis.sentinel.dataNode.password";
private static final String REDIS_SENTINEL_DATA_NODE_DATABASE_CONFIG_PROPERTY = "spring.redis.sentinel.dataNode.database";

private int database;

Expand Down Expand Up @@ -122,6 +127,30 @@ public RedisSentinelConfiguration(PropertySource<?> propertySource) {
String sentinelUsername = String.valueOf(propertySource.getProperty(REDIS_SENTINEL_USERNAME_CONFIG_PROPERTY));
this.setSentinelUsername(sentinelUsername);
}

if (propertySource.containsProperty(REDIS_SENTINEL_DATA_NODE_USERNAME_CONFIG_PROPERTY)) {
String dataNodeUsername = String
.valueOf(propertySource.getProperty(REDIS_SENTINEL_DATA_NODE_USERNAME_CONFIG_PROPERTY));
this.setUsername(dataNodeUsername);
}

if (propertySource.containsProperty(REDIS_SENTINEL_DATA_NODE_PASSWORD_CONFIG_PROPERTY)) {
String dataNodePassword = String
.valueOf(propertySource.getProperty(REDIS_SENTINEL_DATA_NODE_PASSWORD_CONFIG_PROPERTY));
this.setPassword(dataNodePassword);
}

if (propertySource.containsProperty(REDIS_SENTINEL_DATA_NODE_DATABASE_CONFIG_PROPERTY)) {
String databaseSource = String
.valueOf(propertySource.getProperty(REDIS_SENTINEL_DATA_NODE_DATABASE_CONFIG_PROPERTY));
int database;
try {
database = Integer.parseInt(databaseSource);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException(String.format("Invalid DB index '%s'; integer required", databaseSource));
}
this.setDatabase(database);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Collections;
import java.util.HashSet;

import org.assertj.core.api.ThrowableAssert;
import org.junit.jupiter.api.Test;

import org.springframework.mock.env.MockPropertySource;
Expand All @@ -32,6 +33,8 @@
* @author Christoph Strobl
* @author Mark Paluch
* @author Vikas Garg
* @author Samuel Klose
* @author Mustapha Zorgati
*/
class RedisSentinelConfigurationUnitTests {

Expand Down Expand Up @@ -186,4 +189,56 @@ void readSentinelUsernameFromConfigProperty() {
assertThat(config.getSentinelPassword()).isEqualTo(RedisPassword.of("foo"));
assertThat(config.getSentinels()).hasSize(1).contains(new RedisNode("127.0.0.1", 123));
}

@Test // GH-2860
void readSentinelDataNodeUsernameFromConfigProperty() {
MockPropertySource propertySource = new MockPropertySource();
propertySource.setProperty("spring.redis.sentinel.dataNode.username", "datanode-user");

RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource);

assertThat(config.getDataNodeUsername()).isEqualTo("datanode-user");
}

@Test // GH-2860
void readSentinelDataNodePasswordFromConfigProperty() {
MockPropertySource propertySource = new MockPropertySource();
propertySource.setProperty("spring.redis.sentinel.dataNode.password", "datanode-password");

RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource);

assertThat(config.getDataNodePassword()).isEqualTo(RedisPassword.of("datanode-password"));
}

@Test // GH-2860
void readSentinelDataNodeDatabaseFromConfigProperty() {
MockPropertySource propertySource = new MockPropertySource();
propertySource.setProperty("spring.redis.sentinel.dataNode.database", "5");

RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource);

assertThat(config.getDatabase()).isEqualTo(5);
}

@Test // GH-2860
void shouldThrowErrorWhen() {
MockPropertySource propertySource = new MockPropertySource();
propertySource.setProperty("spring.redis.sentinel.dataNode.database", "thisIsNotAnInteger");

ThrowableAssert.ThrowingCallable call = () -> new RedisSentinelConfiguration(propertySource);

assertThatThrownBy(call).isInstanceOf(IllegalArgumentException.class)
.hasMessage("Invalid DB index '%s'; integer required", "thisIsNotAnInteger");
}

@Test // GH-2860
void shouldThrowErrorWhen2() {
MockPropertySource propertySource = new MockPropertySource();
propertySource.setProperty("spring.redis.sentinel.dataNode.database", "null");

ThrowableAssert.ThrowingCallable call = () -> new RedisSentinelConfiguration(propertySource);

assertThatThrownBy(call).isInstanceOf(IllegalArgumentException.class)
.hasMessage("Invalid DB index '%s'; integer required", "null");
}
}