Skip to content

Commit d2cc03e

Browse files
committed
Added config property to run the Container with a fixed name. Updated README and enhanced other documentation.
1 parent 5fead74 commit d2cc03e

File tree

8 files changed

+219
-167
lines changed

8 files changed

+219
-167
lines changed

README.md

+145-130
Large diffs are not rendered by default.

src/main/java/io/github/quinnandrews/spring/local/postgresql/config/PostgreSQLContainerConfig.java

+49-22
Original file line numberDiff line numberDiff line change
@@ -43,27 +43,37 @@ public class PostgreSQLContainerConfig {
4343
private static final Logger logger = LoggerFactory.getLogger(PostgreSQLContainerConfig.class);
4444

4545
private final String containerImage;
46+
private final String containerName;
4647
private final Integer containerPort;
4748
private final Boolean followContainerLog;
4849
private final String databaseName;
4950
private final String username;
5051
private final String password;
5152
private final String initScript;
53+
private final String applicationUsername;
54+
private final String applicationPassword;
5255

5356
/**
5457
* Constructs an instance of this Configuration Class with the given properties.
5558
*
5659
* @param containerImage The Docker Image to use as the Container (optional).
60+
* @param containerName The name to use for the Docker Container when started.
5761
* @param containerPort The port on the Container that should map to PostgreSQL (optional).
58-
* @param followContainerLog Whether to log the log output produced by the Container (optional).
62+
* @param followContainerLog Whether to log the output produced by the Container's logs (optional).
5963
* @param databaseName The name for the database (optional).
60-
* @param username The username of the database super/admin user (optional).
64+
* @param username The username for the database super/admin user (optional).
6165
* @param password The password for the database super/admin user (optional).
66+
* @param applicationUsername The username for the database user the Application should connect with,
67+
* if different from the super/admin user (optional).
68+
* @param applicationPassword The password for the database user the Application should connect with,
69+
* if different from the super/admin user (optional).
6270
* @param initScript The path to an SQL script that should be executed when the Container
6371
* starts (optional).
6472
*/
6573
public PostgreSQLContainerConfig(@Value("${spring.local.postgresql.container.image:#{null}}")
6674
final String containerImage,
75+
@Value("${spring.local.postgresql.container.name:#{null}}")
76+
final String containerName,
6777
@Value("${spring.local.postgresql.container.port:#{null}}")
6878
final Integer containerPort,
6979
@Value("${spring.local.postgresql.container.log.follow:#{false}}")
@@ -74,19 +84,26 @@ public PostgreSQLContainerConfig(@Value("${spring.local.postgresql.container.ima
7484
final String username,
7585
@Value("${spring.local.postgresql.database.password:#{null}}")
7686
final String password,
87+
@Value("${spring.local.postgresql.database.application.username:#{null}}")
88+
final String applicationUsername,
89+
@Value("${spring.local.postgresql.database.application.password:#{null}}")
90+
final String applicationPassword,
7791
@Value("${spring.local.postgresql.database.init.script:#{null}}")
7892
final String initScript) {
7993
this.containerImage = containerImage;
94+
this.containerName = containerName;
8095
this.containerPort = containerPort;
8196
this.followContainerLog = followContainerLog;
8297
this.databaseName = databaseName;
8398
this.username = username;
8499
this.password = password;
100+
this.applicationUsername = applicationUsername;
101+
this.applicationPassword = applicationPassword;
85102
this.initScript = initScript;
86103
}
87104

88105
/**
89-
* Initializes a Testcontainers Bean that runs PostgreSQL inside a Docker Container
106+
* Returns a Testcontainers Bean that runs PostgreSQL inside a Docker Container
90107
* with the given configuration.
91108
*
92109
* @return PostgreSQLContainer
@@ -99,12 +116,14 @@ public PostgreSQLContainer<?> postgreSQLContainer() {
99116
.orElse(POSTGRESQL_DEFAULT_IMAGE))
100117
);
101118
Optional.ofNullable(containerPort).ifPresent(cp ->
102-
container.withCreateContainerCmdModifier(cmd -> cmd.withHostConfig(
103-
new HostConfig().withPortBindings(
104-
new PortBinding(Ports.Binding.bindPort(cp),
105-
new ExposedPort(PostgreSQLContainer.POSTGRESQL_PORT)))
106-
))
107-
);
119+
container.withCreateContainerCmdModifier(cmd -> cmd
120+
.withName(containerName)
121+
.withHostConfig(
122+
new HostConfig().withPortBindings(
123+
new PortBinding(
124+
Ports.Binding.bindPort(cp),
125+
new ExposedPort(PostgreSQLContainer.POSTGRESQL_PORT))
126+
))));
108127
if (followContainerLog) {
109128
container.withLogConsumer(new Slf4jLogConsumer(logger));
110129
}
@@ -121,32 +140,40 @@ public PostgreSQLContainer<?> postgreSQLContainer() {
121140
122141
Running PostgreSQLContainer for development and testing.
123142
124-
Built with Docker Image: {0}
143+
Container: {0}
144+
Image: {1}
145+
Port Mapping: {2}:{3}
146+
147+
Use the credentials below to connect with your client of choice (DBeaver,
148+
IntelliJ IDEA, etc.):
149+
150+
JDBC URL: {4}
151+
Admin User Username: {5}
152+
Admin User Password: {6}
153+
Application User Username: {7}
154+
Application User Password: {8}
125155
126-
Use the credentials below to connect your client of choice (DBeaver,
127-
IntelliJ IDEA, etc.) to the PostgreSQL server inside the container:
128-
129-
JDBC URL: {1}
130-
Username: {2}
131-
Password: {3}
132-
133-
Note: The port referenced in the JDBC URL is a port to access the
134-
container. Inside the container PostgreSQL is on port 5432 as usual.
135-
136156
|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|
137157
*************************************************************************************
138158
""",
159+
container.getContainerName(),
139160
container.getDockerImageName(),
161+
String.valueOf(container.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT)),
162+
String.valueOf(PostgreSQLContainer.POSTGRESQL_PORT),
140163
container.getJdbcUrl(),
141164
container.getUsername(),
142-
container.getPassword()));
165+
container.getPassword(),
166+
Optional.ofNullable(applicationUsername)
167+
.orElse("[not configured]"),
168+
Optional.ofNullable(applicationPassword)
169+
.orElse("[not configured]")));
143170
return container;
144171
}
145172

146173
/**
147174
* Initializes a Spring Bean connecting the Application to the PostgreSQLContainer.
148175
*
149-
* @param applicationUsername The username of the database user the Application should connect with,
176+
* @param applicationUsername The username for the database user the Application should connect with,
150177
* if different from the super/admin user (optional).
151178
* @param applicationPassword The password for the database user the Application should connect with,
152179
* if different from the super/admin user (optional).

src/main/resources/META-INF/additional-spring-configuration-metadata.json

+16-10
Original file line numberDiff line numberDiff line change
@@ -3,61 +3,67 @@
33
{
44
"name": "spring.local.postgresql.engaged",
55
"type": "java.lang.Boolean",
6-
"description": "Whether the embedded, containerized PostgreSQL database should be configured to start when the Application starts.",
6+
"description": "Whether the containerized PostgreSQL database should be configured and started when the Application starts.",
77
"defaultValue": true
88
},
99
{
1010
"name": "spring.local.postgresql.container.image",
1111
"type": "java.lang.String",
12-
"description": "The name of a Docker Image containing a given version of PostgreSQL (example: postgres:15). If undefined, the Testcontainers default of 'postgres:9.6.12' is used.",
12+
"description": "The Docker Image with the chosen version of PostgreSQL (example: postgres:15). If undefined, Testcontainers will use its default ('postgres:9.6.12').",
1313
"defaultValue": "postgres:9.6.12"
1414
},
15+
{
16+
"name": "spring.local.postgresql.container.name",
17+
"type": "java.lang.String",
18+
"description": "The name to use for the Docker Container when started. If undefined, a random name is used. Random names are preferred for Integration Tests, but when running the Application locally, a fixed name is useful, since it allows developers to find the running container with a consistent, predictable name.",
19+
"defaultValue": "[random name assignment]"
20+
},
1521
{
1622
"name": "spring.local.postgresql.container.port",
1723
"type": "java.lang.Integer",
18-
"description": "The port on the Docker Container that should map to the port used by PostgreSQL inside the container. If undefined, a random port is used, which is preferred for integration tests, but when running the Application locally, defining a fixed port is useful. It gives developers the ability to configure a JDBC client with a consistent port. Otherwise, the port in the client's configuration must be updated if the Application had been restarted since the client was last used.",
24+
"description": "The port on the Docker Container to map with the PostgreSQL port inside the container. If undefined, a random port is used. Random ports are preferred for Integration Tests, but when running the Application locally, a fixed port is useful, since it allows developers to configure any connecting, external tools or apps with a consistent, predictable port.",
1925
"defaultValue": "[random port assignment]"
2026
},
2127
{
2228
"name": "spring.local.postgresql.container.log.follow",
2329
"type": "java.lang.Boolean",
24-
"description": "Whether the Application should log the log output produced by the Container.",
30+
"description": "Whether the Application should log the output produced by the Container's log.",
2531
"defaultValue": false
2632
},
2733
{
2834
"name": "spring.local.postgresql.database.name",
2935
"type": "java.lang.String",
30-
"description": "The name of the PostgreSQL database the Application will connect to. If undefined, defaults to the Testcontainers default of 'test'.",
36+
"description": "The name to use for the PostgreSQL database. If undefined, Testcontainers will use its default (test).",
3137
"defaultValue": "test"
3238
},
3339
{
3440
"name": "spring.local.postgresql.database.username",
3541
"type": "java.lang.String",
36-
"description": "The username of an admin or superuser in the PostgreSQL database. If no 'spring.local.postgresql.database.application.username' is defined, this will also be the username the Application uses to connect. If undefined, defaults to the Testcontainers default of 'test'.",
42+
"description": "The username of an admin or superuser in the PostgreSQL database. If 'spring.local.postgresql.database.application.username' is not defined, this will also be the username the Application uses to connect. If undefined, Testcontainers will use its default ('test').",
3743
"defaultValue": "test"
3844
},
3945
{
4046
"name": "spring.local.postgresql.database.password",
4147
"type": "java.lang.String",
42-
"description": "The password that goes with the username of the admin or superuser in the PostgreSQL database. If no 'spring.local.postgresql.database.application.username' is defined, this will also be the password for the username the Application uses to connect. If undefined, defaults to the Testcontainers default of 'test'.",
48+
"description": "The password that goes with the username of the admin or superuser in the PostgreSQL database. If 'spring.local.postgresql.database.application.username' is not defined, this will also be the password for the username the Application uses to connect. If undefined, Testcontainers will use its default ('test').",
4349
"defaultValue": "test"
4450
},
4551
{
4652
"name": "spring.local.postgresql.database.application.username",
4753
"type": "java.lang.String",
48-
"description": "In most cases the database user used by the Application should not have admin or superuser privileges. This property provides the ability to define the username of an \"application user\" for use during testing and local development. The Application will use this username to connect to the PostgreSQL database. If undefined, the value defined by 'spring.local.postgresql.database.username' will be used instead. NOTE: This application user is NOT automatically created. An init-script is required to create the user and grant their initial privileges.",
54+
"description": "In most cases the database user used by the Application should not have admin or superuser privileges. This property provides the ability to define the username of an \"application user\" for use during testing and local development. The Application will use this username to connect to the PostgreSQL database. If undefined, the value defined by 'spring.local.postgresql.database.username' will be used instead. NOTE: The application user will NOT be created automatically. An init-script is required to create the user and grant their initial privileges.",
4955
"defaultValue": null
5056
},
5157
{
5258
"name": "spring.local.postgresql.database.application.password",
5359
"type": "java.lang.String",
54-
"description": "In most cases the database user used by the Application should not have admin or superuser privileges. This property provides the ability to define the password for the username of an \"application user\" for use during testing and local development. The Application will use this password to connect to the PostgreSQL database. If undefined, the value defined by 'spring.local.postgresql.database.password' will be used instead. NOTE: This application user is NOT automatically created. An init-script is required to create the user and grant their initial privileges.",
60+
"description": "In most cases the database user used by the Application should not have admin or superuser privileges. This property provides the ability to define the password for the username of an \"application user\" for use during testing and local development. The Application will use this password to connect to the PostgreSQL database. If undefined, the value defined by 'spring.local.postgresql.database.password' will be used instead. NOTE: The application user will NOT be created automatically. An init-script is required to create the user and grant their initial privileges.",
5561
"defaultValue": null
5662
},
5763
{
5864
"name": "spring.local.postgresql.database.init.script",
5965
"type": "java.lang.String",
60-
"description": "The path to an SQL file (beginning with the 'resources' directory as the root) that should be executed when the Docker Container starts. Executes before migrations. Useful for administrative tasks, like creating additional users, for example. If undefined, no script is executed.",
66+
"description": "The path to an SQL file (with the 'resources' directory as the root) that should be executed when the Docker Container starts. Executes before migrations. Useful for administrative tasks, like creating additional users, for example. If undefined, no script is executed.",
6167
"defaultValue": null
6268
}
6369
]

src/test/java/io/github/quinnandrews/spring/local/postgresql/AppUserPostgreSQLContainerConfigTest.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package io.github.quinnandrews.spring.local.postgresql;
22

33
import com.zaxxer.hikari.HikariDataSource;
4+
import io.github.quinnandrews.spring.local.postgresql.application.Application;
5+
import io.github.quinnandrews.spring.local.postgresql.application.data.guitarpedals.repository.GuitarPedalRepository;
46
import org.junit.jupiter.api.MethodOrderer;
57
import org.junit.jupiter.api.Order;
68
import org.junit.jupiter.api.Test;
79
import org.junit.jupiter.api.TestMethodOrder;
8-
import io.github.quinnandrews.spring.local.postgresql.application.Application;
9-
import io.github.quinnandrews.spring.local.postgresql.application.data.guitarpedals.repository.GuitarPedalRepository;
1010
import org.springframework.beans.factory.annotation.Autowired;
1111
import org.springframework.boot.test.context.SpringBootTest;
1212
import org.springframework.data.domain.Sort;
@@ -43,6 +43,7 @@ void container_initialized() {
4343
assertTrue(postgreSQLContainer.isRunning());
4444
// then the container matches the 'appuser' configuration
4545
assertEquals("postgres:15", postgreSQLContainer.getDockerImageName());
46+
assertEquals("/local_postgresql", postgreSQLContainer.getContainerName());
4647
assertEquals(15432, postgreSQLContainer.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT));
4748
assertEquals("pedals", postgreSQLContainer.getDatabaseName());
4849
assertEquals("fuzz", postgreSQLContainer.getUsername());

src/test/java/io/github/quinnandrews/spring/local/postgresql/CustomPostgreSQLContainerConfigTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ void container_initialized() {
4040
assertTrue(postgreSQLContainer.isRunning());
4141
// then the container matches the 'custom' configuration
4242
assertEquals("postgres:15", postgreSQLContainer.getDockerImageName());
43+
assertEquals("/local_postgresql", postgreSQLContainer.getContainerName());
4344
assertEquals(15432, postgreSQLContainer.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT));
4445
assertEquals("pedals", postgreSQLContainer.getDatabaseName());
4546
assertEquals("fuzz", postgreSQLContainer.getUsername());

src/test/java/io/github/quinnandrews/spring/local/postgresql/DefaultPostgreSQLContainerConfigTest.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package io.github.quinnandrews.spring.local.postgresql;
22

33
import com.zaxxer.hikari.HikariDataSource;
4+
import io.github.quinnandrews.spring.local.postgresql.application.Application;
5+
import io.github.quinnandrews.spring.local.postgresql.application.data.guitarpedals.repository.GuitarPedalRepository;
6+
import io.github.quinnandrews.spring.local.postgresql.config.PostgreSQLContainerConfig;
47
import org.junit.jupiter.api.MethodOrderer;
58
import org.junit.jupiter.api.Order;
69
import org.junit.jupiter.api.Test;
710
import org.junit.jupiter.api.TestMethodOrder;
8-
import io.github.quinnandrews.spring.local.postgresql.application.Application;
9-
import io.github.quinnandrews.spring.local.postgresql.application.data.guitarpedals.repository.GuitarPedalRepository;
10-
import io.github.quinnandrews.spring.local.postgresql.config.PostgreSQLContainerConfig;
1111
import org.springframework.beans.factory.annotation.Autowired;
1212
import org.springframework.boot.test.context.SpringBootTest;
1313
import org.springframework.data.domain.Sort;

src/test/resources/application-appuser.properties

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#spring.local.postgresql.engaged=true
44

55
spring.local.postgresql.container.image=postgres:15
6+
spring.local.postgresql.container.name=local_postgresql
67
spring.local.postgresql.container.port=15432
78
spring.local.postgresql.database.name=pedals
89
spring.local.postgresql.database.username=fuzz

src/test/resources/application-custom.properties

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#spring.local.postgresql.engaged=true
44

55
spring.local.postgresql.container.image=postgres:15
6+
spring.local.postgresql.container.name=local_postgresql
67
spring.local.postgresql.container.port=15432
78
spring.local.postgresql.database.name=pedals
89
spring.local.postgresql.database.username=fuzz

0 commit comments

Comments
 (0)