Skip to content

enhancement: Easier configuration of the postgres command #9629

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 @@ -4,9 +4,14 @@
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.utility.DockerImageName;

import lombok.NonNull;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Testcontainers implementation for PostgreSQL.
Expand Down Expand Up @@ -39,7 +44,7 @@ public class PostgreSQLContainer<SELF extends PostgreSQLContainer<SELF>> extends

private String password = "test";

private static final String FSYNC_OFF_OPTION = "fsync=off";
private final Map<String, String> CONFIG_OPTIONS = new HashMap<>(Map.of("fsync", "off"));

/**
* @deprecated use {@link #PostgreSQLContainer(DockerImageName)} or {@link #PostgreSQLContainer(String)} instead
Expand All @@ -62,7 +67,6 @@ public PostgreSQLContainer(final DockerImageName dockerImageName) {
.withRegEx(".*database system is ready to accept connections.*\\s")
.withTimes(2)
.withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS));
this.setCommand("postgres", "-c", FSYNC_OFF_OPTION);

addExposedPort(POSTGRESQL_PORT);
}
Expand All @@ -85,6 +89,35 @@ protected void configure() {
addEnv("POSTGRES_DB", databaseName);
addEnv("POSTGRES_USER", username);
addEnv("POSTGRES_PASSWORD", password);

// If user never configured a command, and CONFIG_OPTIONS exist, then generate command
if (this.getContainerDef().getCommand().length == 0 && CONFIG_OPTIONS.size() > 0) {
this.setCommand("postgres -c " + CONFIG_OPTIONS.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(" -c ")));
}
}

/**
* Collects a set of configurations that will be set as a startup command of the PostgreSQL container.
* Note: configuration options will be ignored if a command is set using either withCommand() or setCommand()
*
* <pre>
* For example:
* postgresql.withConfigOption("max_prepared_transactions", "5").withConfigOption("log_destination", "'syslog'");
*
* Will result in the startup command:
* postgres -c max_prepared_transactions=5 -c log_destination='syslog'
* </pre>
*
* @param key The configuration name
* @param value the configuration value
* @return self
*/
public SELF withConfigOption(@NonNull String key, @NonNull String value) {
if(!key.matches("[a-zA-Z0-9_]")) {
throw new IllegalArgumentException("PostgreSQL configuration option with key: " + key + " is an invalid configuration string.");
}
CONFIG_OPTIONS.put(key, value);
return self();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ public void testUnsetCommand() throws SQLException {
}
}

@Test
public void testWithConfigOption() throws SQLException {
try (
PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE)
.withConfigOption("max_connections", "42")
) {
postgres.start();

ResultSet resultSet = performQuery(postgres, "SELECT current_setting('max_connections')");
String result = resultSet.getString(1);
assertThat(result).as("max_connections should be overriden").isEqualTo("42");

// Ensure default config
resultSet = performQuery(postgres, "SELECT current_setting('fsync')");
result = resultSet.getString(1);
assertThat(result).as("fsync should not overriden").isEqualTo("off");
}
}

@Test
public void testMissingInitScript() {
try (
Expand Down
Loading