Skip to content
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

Test upgrading from the latest published minor version #261

Open
wants to merge 397 commits into
base: master
Choose a base branch
from

Conversation

eastlondoner
Copy link
Contributor

@eastlondoner eastlondoner commented Jun 15, 2020

Adds 2 new tests for upgrading from published neo4j docker images to the one just built.

  1. tests upgrade within the same minor version e.g released 4.0 -> 4.0.7-SNAPSHOT
  2. tests upgrade from the previous minor version in the same major version e.g. released 4.0 -> 4.1.0-SNAPSHOT

It seems that the existing DatabaseIO.java and TestUpgrade.java file were indented with tabs so, that got fixed at the same time.

Andrew Jefferson and others added 30 commits May 25, 2019 12:43
Check groups when determining if a directory is writable
…ning-to-stdout

Send warning about chowning folder to stdout.
Send warning about chowning folder to stdout.
jennyowen added 7 commits May 6, 2020 12:52
We were using a Neo4jContainer from TestContainers rather than a GenericContainer and this
seems to have caused the /data/dbms directory to get built unexpectedly.
The data/dbms folder contains authentication information, and it turns out that Neo4jContainer
was setting a default password even though NEO4J_AUTH=none is set, hence the folder appeared and out tests passed.
I've added an initial password so that the folder is created and we can test permissions on it.
src/test/java/com/neo4j/docker/TestUpgrade.java Outdated Show resolved Hide resolved
src/test/java/com/neo4j/docker/TestUpgrade.java Outdated Show resolved Hide resolved
Comment on lines 90 to 94
if ( Instant.now().isBefore( Instant.parse( "2020-07-01T00:00:00.00Z" ) ) )
{
// This sort-of-hack is necessary when we cut a new minor branch before the previous minor branch has been published to dockerhub.
Assumptions.assumeTrue( Neo4jVersion.NEO4J_VERSION_420.isNewerThan( targetNeo4jVersion ) );
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is hacky. I think the question of "is this on a branch that's released already" should be captured in the Neo4jVersion class somehow. I think marking all patch=0 versions as unreleased (which would be true in our CI environment and in general) would be enough right?
We don't really need to worry too much about people updating from, say, 4.0.0 to 4.0.0. It's not a valid thing that users will ever do. Can't we just skip this test for if patch == 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the main Neo4j Jars we say that going from 1 minor version to another is supported.
For clustering two adjacent minor versions are required to form a functioning cluster (necessary for no-downtime upgrades).
So my intention is to test that migration to x.y.0 from x.y-1 works.

The problem I'm trying to tackle is that there is a period (like now) when 4.2.0 exists internally (so these tests will be run in PRs etc.) but there is no published 4.1 to test upgrade from.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just do that kind of upgrade in a separate unit test rather than having over-complicated test logic here? Actually that would simplify the logic a lot since the latest patch version of a release is always tagged as the major.minor. EG neo4j:4.0 is always the latest 4.0 patch version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will separate so we will do:

  1. patch upgrade tests I.e. from x.y (released) to current head (assuming current head patch version > 0)

  2. Minor version upgrade test I.e. from x.(y-1) to current head.

For the latter there will still need to be a temporary hack for situations like at the moment where there is a 4.2 branch but no 4.1 release.

What’s going on should be much more transparent though

src/test/java/com/neo4j/docker/TestUpgrade.java Outdated Show resolved Hide resolved
src/test/java/com/neo4j/docker/TestUpgrade.java Outdated Show resolved Hide resolved
}
catch ( IOException e )
{
throw new RuntimeException( e );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the IOException being recast as a runtime exception? Also, doesn't the method signature need to declare that it throws an exception?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RuntimeExceptions are unchecked (don't need to be declared).

I used createDirectory in a stream processing step and those aren't allowed to throw checked exceptions - this is a just wrapping the checked IOException in a RuntimeException so I can use this method on a stream.

Comment on lines 45 to 46
container.setWaitStrategy( Wait.forHttp( "/" ).forPort( 7474 ).forStatusCode( 200 ) );
container = container.withStartupTimeout( Duration.ofMinutes( 2 ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do this simpler like:

.waitingFor( Wait.forHttp( "/" )
.forPort( 7474 )
.forStatusCode( 200 )
.withStartupTimeout( Duration.ofSeconds( 90 ) ) );

validateConfig( db );

// validate that writes actually went to the mounted directories
writableMounts.forEach( ( containerMount, hostFolder ) -> assertDirectoryModifiedSince( hostFolder, startTime ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have tests that check that the container can write to a mounted folder, so I'm not sure what value this adds?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I didn't include this check to check that mount paths worked. I include it because without checking if we changed how the mount paths worked (e.g. /data became /databases) this test would still pass (using /data) but it wouldn't be doing what I intended it to do which is persisting data on that mount.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but there's already a check that the data has been persisted:
db.verifyDataInContainer( user, password ); on line 146

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn’t check that the data is in the mounted directory - just that it’s in neo4j

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the second container, we don't write the data again before checking that the data is there. How else would the data be there unless it's reading from the mounted folder?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m checking that subsequent writes succeed and go there.
admittedly perhaps a niche concern.
It’s not just the data folder though - it’s all the writable folders so logs etc as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's valid to check that we can still write to the database with the mounted folder since we might have introduced permissions changes (eg new uid!). I just don't think we need to query the file system to do that when we are also actually writing something to the database, since the database write will fail if something on the file system changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stand by this. The writing of metrics to /metrics is broken in 3.5 if the volume is mounted without permissions even when running as root. That is detected by this check.

If I remove this check we do not detect that brokenness and this test passes when it should not.

private String dockerImageToUpgradeFrom( Neo4jVersion targetNeo4jVersion )
{
// The most recent minor release that we expect to already have been released.
var minorVersionToUpgradeFrom = targetNeo4jVersion.patch == 0 ? targetNeo4jVersion.minor - 1 : targetNeo4jVersion.minor;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the logic here confuses me. My understanding of these tests is that we're supposed to be testing upgrade of patch versions. So if the patch version is 0, we wouldn't ever need to upgrade within major/minor, right? The test is redundant if patch version = 0.

However there is confusing logic here and earlier with the 4.2 time checking hack, which seem to deal with the case of when patch = 0. Also I think this test will (in its current state) run on 4.1 even now before 4.1.0 is released?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're working on different assumptions. I want this test to run on 4.1.0 to test 4.0 -> 4.1.0

My understanding is that for Neo4j going from one minor version to the next is expected to work without config changes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that should be a separate unit test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is split out into separate tests now.

src/test/java/com/neo4j/docker/TestUpgrade.java Outdated Show resolved Hide resolved
@@ -3,86 +3,111 @@
import org.junit.jupiter.api.Assertions;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry the diff here is large but the file was indented with tabs so I let the IDE re-indent the whole thing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants