Skip to content
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
10 changes: 5 additions & 5 deletions docs/modules/databases/neo4j.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ If you need the Neo4j enterprise license, you can declare your Neo4j container l
[Enterprise edition](../../../modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerTest.java) inside_block:enterpriseEdition
<!--/codeinclude-->

This creates a Testcontainers based on the Docker image build with the Enterprise version of Neo4j 4.4.
The call to `withEnterpriseEdition` adds the required environment variable that you accepted the terms and condition of the enterprise version.
You accept those by adding a file named `container-license-acceptance.txt` to the root of your classpath containing the text `neo4j:4.4-enterprise` in one line.
!!! warning
the `withEnterpriseEdition` method is deprecated because it was implicitly changing the image tag to be always version 4.4.

If you are planning to run a newer Neo4j 5.x enterprise edition image, you have to manually define the proper enterprise image (e.g. `neo4j:5-enterprise`)
and set the environment variable `NEO4J_ACCEPT_LICENSE_AGREEMENT` by adding `.withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes")` to your container definition.
This creates a Testcontainers container based on the Docker image build with the Enterprise version of the defined tag.
The call to `withEnterpriseImage` adds the required environment variable that you accepted the terms and condition of the enterprise version.
You accept those by adding a file named `container-license-acceptance.txt` to the root of your classpath containing the text `neo4j:<tag>-enterprise` in one line.

You'll find more information about licensing Neo4j here: [About Neo4j Licenses](https://neo4j.com/licensing/).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@
public class Neo4jContainer extends GenericContainer<Neo4jContainer> {

/**
* The image defaults to the official Neo4j image: <a href="https://hub.docker.com/_/neo4j/">Neo4j</a>.
* The default tag (version) to use.
* @deprecated this should not be used anywhere besides also deprecated method {@link #withEnterpriseEdition()}
*/
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("neo4j");
private static final String ENTERPRISE_TAG_4_4 = "4.4-enterprise";

/**
* The default tag (version) to use.
* The image defaults to the official Neo4j image: <a href="https://hub.docker.com/_/neo4j/">Neo4j</a>.
*/
private static final String DEFAULT_TAG = "4.4";
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("neo4j");

private static final String ENTERPRISE_TAG = DEFAULT_TAG + "-enterprise";
private static final String ENTERPRISE_SUFFIX = "-enterprise";

/**
* Default port for the binary Bolt protocol.
Expand Down Expand Up @@ -204,15 +205,40 @@ public String getHttpsUrl() {
* needs either a commercial, education or evaluation license.
*
* @return This container.
* @deprecated This method will force the use of the old 4.4. (LTS) version to be used as the enterprise image,
* use {@link #withEnterpriseImage} to actively accept the license and use the enterprise version of
* the initial defined community version.
*/
public Neo4jContainer withEnterpriseEdition() {
if (!standardImage) {
throw new IllegalStateException(
String.format("Cannot use enterprise version with alternative image %s.", getDockerImageName())
);
}
setDockerImageName(DEFAULT_IMAGE_NAME.withTag(ENTERPRISE_TAG_4_4).asCanonicalNameString());
LicenseAcceptance.assertLicenseAccepted(getDockerImageName());

setDockerImageName(DEFAULT_IMAGE_NAME.withTag(ENTERPRISE_TAG).asCanonicalNameString());
addEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes");

return self();
}

/**
* Configures the container to use the enterprise edition of the default docker image.
* <br><br>
* Please have a look at the <a href="https://neo4j.com/licensing/">Neo4j Licensing page</a>. While the Neo4j
* Community Edition can be used for free in your projects under the GPL v3 license, Neo4j Enterprise edition
* needs either a commercial, education or evaluation license.
*
* @return This container.
*/
public Neo4jContainer withEnterpriseImage() {
if (!standardImage) {
throw new IllegalStateException(
String.format("Cannot use enterprise version with alternative image %s.", getDockerImageName())
);
}
setDockerImageName(DockerImageName.parse(getDockerImageName() + ENTERPRISE_SUFFIX).asCanonicalNameString());
LicenseAcceptance.assertLicenseAccepted(getDockerImageName());

addEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ class Neo4jContainerTest {
// See org.testcontainers.utility.LicenseAcceptance#ACCEPTANCE_FILE_NAME
private static final String ACCEPTANCE_FILE_LOCATION = "/container-license-acceptance.txt";

private static final String DOCKER_IMAGE_NAME = "neo4j:5.26";

@Test
void shouldDisableAuthentication() {
try (
// spotless:off
// withoutAuthentication {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4")
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME)
.withoutAuthentication()
// }
// spotless:on
Expand Down Expand Up @@ -72,22 +74,22 @@ void shouldCopyDatabase() {
void shouldFailOnCopyDatabaseForDefaultNeo4j4Image() {
assertThatIllegalArgumentException()
.isThrownBy(() -> {
new Neo4jContainer("neo4j:4.4.1").withDatabase(MountableFile.forClasspathResource("/test-graph.db"));
new Neo4jContainer("neo4j:4.4").withDatabase(MountableFile.forClasspathResource("/test-graph.db"));
})
.withMessage("Copying database folder is not supported for Neo4j instances with version 4.0 or higher.");
}

@Test
void shouldFailOnCopyDatabaseForCustomNeo4j4Image() {
void shouldFailOnCopyDatabaseForCustomNeo4j5Image() {
assertThatIllegalArgumentException()
.isThrownBy(() -> {
new Neo4jContainer("neo4j:4.4.1").withDatabase(MountableFile.forClasspathResource("/test-graph.db"));
new Neo4jContainer("neo4j:5.26").withDatabase(MountableFile.forClasspathResource("/test-graph.db"));
})
.withMessage("Copying database folder is not supported for Neo4j instances with version 4.0 or higher.");
}

@Test
void shouldFailOnCopyDatabaseForCustomNonSemverNeo4j4Image() {
void shouldFailOnCopyDatabaseForCustomNonSemverNeo4jLatestImage() {
assertThatIllegalArgumentException()
.isThrownBy(() -> {
new Neo4jContainer("neo4j:latest").withDatabase(MountableFile.forClasspathResource("/test-graph.db"));
Expand All @@ -99,7 +101,7 @@ void shouldFailOnCopyDatabaseForCustomNonSemverNeo4j4Image() {
void shouldCopyPlugins() {
try (
// registerPluginsPath {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4")
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME)
.withPlugins(MountableFile.forClasspathResource("/custom-plugins"))
// }
) {
Expand All @@ -114,7 +116,7 @@ void shouldCopyPlugins() {
void shouldCopyPlugin() {
try (
// registerPluginsJar {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4")
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME)
.withPlugins(MountableFile.forClasspathResource("/custom-plugins/hello-world.jar"))
// }
) {
Expand Down Expand Up @@ -149,8 +151,8 @@ void shouldRunEnterprise() {

try (
// enterpriseEdition {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4")
.withEnterpriseEdition()
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME)
.withEnterpriseImage()
// }
.withAdminPassword("Picard123")
) {
Expand All @@ -169,7 +171,7 @@ void shouldRunEnterprise() {
@Test
void shouldAddConfigToEnvironment() {
// neo4jConfiguration {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4")
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME)
.withNeo4jConfig("dbms.security.procedures.unrestricted", "apoc.*,algo.*")
.withNeo4jConfig("dbms.tx_log.rotation.size", "42M");
// }
Expand All @@ -181,7 +183,7 @@ void shouldAddConfigToEnvironment() {

@Test
void shouldRespectEnvironmentAuth() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").withEnv("NEO4J_AUTH", "neo4j/secret");
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).withEnv("NEO4J_AUTH", "neo4j/secret");

neo4jContainer.configure();

Expand All @@ -191,7 +193,7 @@ void shouldRespectEnvironmentAuth() {
@Test
void shouldSetCustomPasswordCorrectly() {
// withAdminPassword {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").withAdminPassword("verySecret");
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).withAdminPassword("verySecret");
// }

neo4jContainer.configure();
Expand All @@ -201,7 +203,7 @@ void shouldSetCustomPasswordCorrectly() {

@Test
void containerAdminPasswordOverrulesEnvironmentAuth() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4")
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME)
.withEnv("NEO4J_AUTH", "neo4j/secret")
.withAdminPassword("anotherSecret");

Expand All @@ -212,7 +214,7 @@ void containerAdminPasswordOverrulesEnvironmentAuth() {

@Test
void containerWithoutAuthenticationOverrulesEnvironmentAuth() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4")
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME)
.withEnv("NEO4J_AUTH", "neo4j/secret")
.withoutAuthentication();

Expand All @@ -223,7 +225,7 @@ void containerWithoutAuthenticationOverrulesEnvironmentAuth() {

@Test
void shouldRespectAlreadyDefinedPortMappingsBolt() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").withExposedPorts(7687);
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).withExposedPorts(7687);

neo4jContainer.configure();

Expand All @@ -232,7 +234,7 @@ void shouldRespectAlreadyDefinedPortMappingsBolt() {

@Test
void shouldRespectAlreadyDefinedPortMappingsHttp() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").withExposedPorts(7474);
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).withExposedPorts(7474);

neo4jContainer.configure();

Expand All @@ -241,7 +243,7 @@ void shouldRespectAlreadyDefinedPortMappingsHttp() {

@Test
void shouldRespectAlreadyDefinedPortMappingsWithoutHttps() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").withExposedPorts(7687, 7474);
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).withExposedPorts(7687, 7474);

neo4jContainer.configure();

Expand All @@ -250,7 +252,7 @@ void shouldRespectAlreadyDefinedPortMappingsWithoutHttps() {

@Test
void shouldDefaultExportBoltHttpAndHttps() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4");
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME);

neo4jContainer.configure();

Expand All @@ -259,7 +261,7 @@ void shouldDefaultExportBoltHttpAndHttps() {

@Test
void shouldRespectCustomWaitStrategy() {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").waitingFor(new CustomDummyWaitStrategy());
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).waitingFor(new CustomDummyWaitStrategy());

neo4jContainer.configure();

Expand All @@ -268,7 +270,7 @@ void shouldRespectCustomWaitStrategy() {

@Test
void shouldConfigureSinglePluginByName() {
try (Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").withPlugins("apoc")) {
try (Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).withPlugins("apoc")) {
// needs to get called explicitly for setup
neo4jContainer.configure();

Expand All @@ -280,7 +282,7 @@ void shouldConfigureSinglePluginByName() {
void shouldConfigureMultiplePluginsByName() {
try (
// configureLabsPlugins {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4") //
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME) //
.withPlugins("apoc", "bloom");
// }
) {
Expand All @@ -296,7 +298,7 @@ void shouldConfigureMultiplePluginsByName() {
void shouldCreateRandomUuidBasedPasswords() {
try (
// withRandomPassword {
Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4").withRandomPassword();
Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME).withRandomPassword();
// }
) {
// It will throw an exception if it's not UUID parsable.
Expand All @@ -309,8 +311,8 @@ void shouldCreateRandomUuidBasedPasswords() {

@Test
void shouldWarnOnPasswordTooShort() {
try (Neo4jContainer neo4jContainer = new Neo4jContainer("neo4j:4.4");) {
Logger logger = (Logger) DockerLoggerFactory.getLogger("neo4j:4.4");
try (Neo4jContainer neo4jContainer = new Neo4jContainer(DOCKER_IMAGE_NAME);) {
Logger logger = (Logger) DockerLoggerFactory.getLogger(DOCKER_IMAGE_NAME);
TestLogAppender testLogAppender = new TestLogAppender();
logger.addAppender(testLogAppender);
testLogAppender.start();
Expand Down
Loading