Skip to content

Commit 14ab0d6

Browse files
committed
Use Dockerfile to store the image for the servers
1 parent 5c6d6cf commit 14ab0d6

File tree

23 files changed

+531
-32
lines changed

23 files changed

+531
-32
lines changed

build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ subprojects {
5252
options.encoding = 'UTF-8'
5353
}
5454

55+
// Configure test tasks for all subprojects
56+
tasks.withType( Test ).configureEach {
57+
// Set the project root for finding Docker files - available to all modules
58+
systemProperty 'hibernate.reactive.project.root', rootProject.projectDir.absolutePath
59+
}
60+
5561
if ( !gradle.ext.javaToolchainEnabled ) {
5662
sourceCompatibility = JavaVersion.toVersion( gradle.ext.baselineJavaVersion )
5763
targetCompatibility = JavaVersion.toVersion( gradle.ext.baselineJavaVersion )

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/CockroachDBDatabase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import org.testcontainers.containers.CockroachContainer;
1313
import org.testcontainers.containers.Container;
1414

15-
import static org.hibernate.reactive.containers.DockerImage.imageName;
15+
import static org.hibernate.reactive.containers.DockerImage.fromDockerfile;
1616

1717
class CockroachDBDatabase extends PostgreSQLDatabase {
1818

@@ -25,7 +25,7 @@ class CockroachDBDatabase extends PostgreSQLDatabase {
2525
* TIP: To reuse the same containers across multiple runs, set `testcontainers.reuse.enable=true` in a file located
2626
* at `$HOME/.testcontainers.properties` (create the file if it does not exist).
2727
*/
28-
public static final CockroachContainer cockroachDb = new CockroachContainer( imageName( "cockroachdb/cockroach", "v24.3.13" ) )
28+
public static final CockroachContainer cockroachDb = new CockroachContainer( fromDockerfile( "cockroachdb" ) )
2929
// Username, password and database are not supported by test container at the moment
3030
// Testcontainers will use a database named 'postgres' and the 'root' user
3131
.withReuse( true );

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DB2Database.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
import org.testcontainers.containers.Db2Container;
3030

31-
import static org.hibernate.reactive.containers.DockerImage.imageName;
31+
import static org.hibernate.reactive.containers.DockerImage.fromDockerfile;
3232

3333
class DB2Database implements TestableDatabase {
3434

@@ -87,7 +87,7 @@ class DB2Database implements TestableDatabase {
8787
* TIP: To reuse the same containers across multiple runs, set `testcontainers.reuse.enable=true` in a file located
8888
* at `$HOME/.testcontainers.properties` (create the file if it does not exist).
8989
*/
90-
static final Db2Container db2 = new Db2Container( imageName( "icr.io", "db2_community/db2", "12.1.0.0" ) )
90+
static final Db2Container db2 = new Db2Container( fromDockerfile( "db2" ) )
9191
.withUsername( DatabaseConfiguration.USERNAME )
9292
.withPassword( DatabaseConfiguration.PASSWORD )
9393
.withDatabaseName( DatabaseConfiguration.DB_NAME )

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DockerImage.java

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
*/
66
package org.hibernate.reactive.containers;
77

8+
import java.io.FileNotFoundException;
9+
import java.io.IOException;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.util.List;
13+
814
import org.testcontainers.utility.DockerImageName;
915

1016
/**
@@ -17,15 +23,104 @@
1723
*/
1824
public final class DockerImage {
1925

20-
public static final String DEFAULT_REGISTRY = "docker.io";
21-
22-
public static DockerImageName imageName(String image, String version) {
23-
return imageName( DEFAULT_REGISTRY, image, version );
26+
/**
27+
* Extract the image name and version from the first FROM instruction in the Dockerfile.
28+
* Note that everything else is ignored.
29+
*/
30+
public static DockerImageName fromDockerfile(String databaseName) {
31+
try {
32+
final ImageInformation imageInformation = readFromInstruction( databaseName.toLowerCase() );
33+
return imageName( imageInformation.getRegistry(), imageInformation.getImage(), imageInformation.getVersion() );
34+
}
35+
catch (IOException e) {
36+
throw new RuntimeException( e );
37+
}
2438
}
2539

2640
public static DockerImageName imageName(String registry, String image, String version) {
2741
return DockerImageName
2842
.parse( registry + "/" + image + ":" + version )
2943
.asCompatibleSubstituteFor( image );
3044
}
45+
46+
private static class ImageInformation {
47+
private final String fullImageInfo;
48+
private final String registry;
49+
private final String image;
50+
private final String version;
51+
52+
public ImageInformation(String fullImageInfo) {
53+
// FullImageInfo pattern: <registry>/<image>:<version>
54+
// For example: "docker.io/cockroachdb/cockroach:v24.3.13" becomes registry = "docker.io", image = "cockroachdb/cockroach", version = "v24.3.13"
55+
final int registryEndPos = fullImageInfo.indexOf( '/' );
56+
final int imageEndPos = fullImageInfo.lastIndexOf( ':' );
57+
this.fullImageInfo = fullImageInfo;
58+
this.registry = fullImageInfo.substring( 0, registryEndPos );
59+
this.image = fullImageInfo.substring( registryEndPos + 1, imageEndPos );
60+
this.version = fullImageInfo.substring( imageEndPos + 1 );
61+
}
62+
63+
public String getRegistry() {
64+
return registry;
65+
}
66+
67+
public String getFullImageInfo() {
68+
return fullImageInfo;
69+
}
70+
71+
public String getImage() {
72+
return image;
73+
}
74+
75+
public String getVersion() {
76+
return version;
77+
}
78+
79+
@Override
80+
public String toString() {
81+
return registry + "/" + image + ":" + version;
82+
}
83+
}
84+
85+
private static Path dockerFilePath(String database) {
86+
// Get project root from system property set by Gradle, with fallback
87+
String projectRootProperty = System.getProperty( "hibernate.reactive.project.root" );
88+
Path projectRoot = projectRootProperty != null
89+
? Path.of( projectRootProperty )
90+
: Path.of( System.getProperty( "user.dir" ) );
91+
92+
return projectRoot.resolve( "tooling" ).resolve( "docker" ).resolve( database.toLowerCase() + ".Dockerfile" );
93+
}
94+
95+
private static ImageInformation readFromInstruction(String database) throws IOException {
96+
return readFromInstruction( dockerFilePath( database ) );
97+
}
98+
99+
/**
100+
* Reads a Dockerfile and extracts the first FROM instruction.
101+
*
102+
* @param dockerfilePath path to the Dockerfile
103+
* @return the first FROM instruction found, or empty if none found
104+
* @throws IOException if the file cannot be read
105+
*/
106+
public static ImageInformation readFromInstruction(Path dockerfilePath) throws IOException {
107+
if ( !Files.exists( dockerfilePath ) ) {
108+
throw new FileNotFoundException( "Dockerfile not found: " + dockerfilePath );
109+
}
110+
111+
List<String> lines = Files.readAllLines( dockerfilePath );
112+
for ( String line : lines ) {
113+
// Skip comments and empty lines
114+
String trimmedLine = line.trim();
115+
if ( trimmedLine.isEmpty() || trimmedLine.startsWith( "#" ) ) {
116+
continue;
117+
}
118+
119+
if ( trimmedLine.startsWith( "FROM " ) ) {
120+
return new ImageInformation( trimmedLine.substring( "FROM ".length() ) );
121+
}
122+
}
123+
124+
throw new IOException( " Missing FROM instruction in " + dockerfilePath );
125+
}
31126
}

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MSSQLServerDatabase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
import org.testcontainers.containers.MSSQLServerContainer;
3030

31-
import static org.hibernate.reactive.containers.DockerImage.imageName;
31+
import static org.hibernate.reactive.containers.DockerImage.fromDockerfile;
3232

3333
/**
3434
* The JDBC driver syntax is:
@@ -96,7 +96,7 @@ class MSSQLServerDatabase implements TestableDatabase {
9696
* TIP: To reuse the same containers across multiple runs, set `testcontainers.reuse.enable=true` in a file located
9797
* at `$HOME/.testcontainers.properties` (create the file if it does not exist).
9898
*/
99-
public static final MSSQLServerContainer<?> mssqlserver = new MSSQLServerContainer<>( imageName( "mcr.microsoft.com", "mssql/server", "2022-latest" ) )
99+
public static final MSSQLServerContainer<?> mssqlserver = new MSSQLServerContainer<>( fromDockerfile( "sqlserver" ) )
100100
.acceptLicense()
101101
.withPassword( PASSWORD )
102102
.withReuse( true );

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MariaDatabase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import org.testcontainers.containers.MariaDBContainer;
1515

16-
import static org.hibernate.reactive.containers.DockerImage.imageName;
16+
import static org.hibernate.reactive.containers.DockerImage.fromDockerfile;
1717

1818
class MariaDatabase extends MySQLDatabase {
1919

@@ -36,7 +36,7 @@ class MariaDatabase extends MySQLDatabase {
3636
* TIP: To reuse the same containers across multiple runs, set `testcontainers.reuse.enable=true` in a file located
3737
* at `$HOME/.testcontainers.properties` (create the file if it does not exist).
3838
*/
39-
public static final MariaDBContainer<?> maria = new MariaDBContainer<>( imageName( "mariadb", "11.7.2" ) )
39+
public static final MariaDBContainer<?> maria = new MariaDBContainer<>( fromDockerfile( "maria" ) )
4040
.withUsername( DatabaseConfiguration.USERNAME )
4141
.withPassword( DatabaseConfiguration.PASSWORD )
4242
.withDatabaseName( DatabaseConfiguration.DB_NAME )

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
package org.hibernate.reactive.containers;
77

8-
import static org.hibernate.reactive.containers.DockerImage.imageName;
8+
import static org.hibernate.reactive.containers.DockerImage.fromDockerfile;
99

1010
import java.io.Serializable;
1111
import java.math.BigDecimal;
@@ -87,7 +87,7 @@ class MySQLDatabase implements TestableDatabase {
8787
* TIP: To reuse the same containers across multiple runs, set `testcontainers.reuse.enable=true` in a file located
8888
* at `$HOME/.testcontainers.properties` (create the file if it does not exist).
8989
*/
90-
public static final MySQLContainer<?> mysql = new MySQLContainer<>( imageName( "mysql", "9.2.0") )
90+
public static final MySQLContainer<?> mysql = new MySQLContainer<>( fromDockerfile( "mysql" ) )
9191
.withUsername( DatabaseConfiguration.USERNAME )
9292
.withPassword( DatabaseConfiguration.PASSWORD )
9393
.withDatabaseName( DatabaseConfiguration.DB_NAME )

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/OracleDatabase.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
import org.testcontainers.containers.OracleContainer;
3131

32-
import static org.hibernate.reactive.containers.DockerImage.imageName;
32+
import static org.hibernate.reactive.containers.DockerImage.fromDockerfile;
3333

3434
/**
3535
* Connection string for Oracle thin should be something like:
@@ -88,9 +88,7 @@ class OracleDatabase implements TestableDatabase {
8888
}
8989
}
9090

91-
public static final OracleContainer oracle = new OracleContainer(
92-
imageName( "gvenzl/oracle-free", "23-slim-faststart" )
93-
.asCompatibleSubstituteFor( "gvenzl/oracle-xe" ) )
91+
public static final OracleContainer oracle = new OracleContainer( fromDockerfile( "oracle" ).asCompatibleSubstituteFor( "gvenzl/oracle-xe" ) )
9492
.withUsername( DatabaseConfiguration.USERNAME )
9593
.withPassword( DatabaseConfiguration.PASSWORD )
9694
.withDatabaseName( DatabaseConfiguration.DB_NAME )

hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/PostgreSQLDatabase.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
*/
66
package org.hibernate.reactive.containers;
77

8-
import static org.hibernate.reactive.containers.DockerImage.imageName;
9-
108
import java.io.Serializable;
119
import java.math.BigDecimal;
1210
import java.math.BigInteger;
@@ -30,9 +28,11 @@
3028

3129
import org.testcontainers.containers.PostgreSQLContainer;
3230

31+
import static org.hibernate.reactive.containers.DockerImage.fromDockerfile;
32+
3333
class PostgreSQLDatabase implements TestableDatabase {
3434

35-
public static PostgreSQLDatabase INSTANCE = new PostgreSQLDatabase();
35+
public static final PostgreSQLDatabase INSTANCE = new PostgreSQLDatabase();
3636

3737
private static Map<Class<?>, String> expectedDBTypeForClass = new HashMap<>();
3838

@@ -87,7 +87,7 @@ class PostgreSQLDatabase implements TestableDatabase {
8787
* TIP: To reuse the same containers across multiple runs, set `testcontainers.reuse.enable=true` in a file located
8888
* at `$HOME/.testcontainers.properties` (create the file if it does not exist).
8989
*/
90-
public static final PostgreSQLContainer<?> postgresql = new PostgreSQLContainer<>( imageName( "postgres", "17.5" ) )
90+
public static final PostgreSQLContainer<?> postgresql = new PostgreSQLContainer<>( fromDockerfile( "postgresql" ) )
9191
.withUsername( DatabaseConfiguration.USERNAME )
9292
.withPassword( DatabaseConfiguration.PASSWORD )
9393
.withDatabaseName( DatabaseConfiguration.DB_NAME )
@@ -122,9 +122,8 @@ private String address() {
122122
// Calling start() will start the container (if not already started)
123123
// It is required to call start() before obtaining the JDBC URL because it will contain a randomized port
124124
postgresql.start();
125-
// Latest Postgres JDBC driver has dropped support for loggerLevel
126-
// and the Vert.x driver throws an exception because it does not recognize it
127-
return postgresql.getJdbcUrl().replace( "?loggerLevel=OFF", "" );
125+
// Copied from PostgresSQLContainer#getJdbcUrl
126+
return "jdbc:postgresql://" + postgresql.getHost() + ":" + postgresql.getMappedPort( PostgreSQLContainer.POSTGRESQL_PORT ) + "/" + postgresql.getDatabaseName();
128127
}
129128

130129
return getRegularJdbcUrl();

integration-tests/bytecode-enhancements-it/src/test/java/org/hibernate/reactive/it/BaseReactiveIT.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ public abstract class BaseReactiveIT {
5151
// These properties are in DatabaseConfiguration in core
5252
public static final boolean USE_DOCKER = Boolean.getBoolean( "docker" );
5353

54-
public static final DockerImageName IMAGE_NAME = DockerImageName
55-
.parse( "docker.io/postgres:17.5" )
56-
.asCompatibleSubstituteFor( "postgres" );
54+
public static final DockerImageName IMAGE_NAME = DockerImage.fromDockerfile( "postgresql" );
5755

5856
public static final String USERNAME = "hreact";
5957
public static final String PASSWORD = "hreact";

0 commit comments

Comments
 (0)