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

[Fix] JDK is successfully installed if bin/java files exist #452

Merged
merged 15 commits into from
Nov 4, 2024

Conversation

crogoz
Copy link
Contributor

@crogoz crogoz commented Oct 30, 2024

Before this PR

Context: https://pl.ntr/2p9
We consider that a JDK was successfully installed if the directory exists.
However, this is not always true. eg. if an exception happens while the JDK is copied over to the destination directory (https://github.com/palantir/gradle-jdks/blob/develop/gradle-jdks-setup/src/main/java/com/palantir/gradle/jdks/setup/GradleJdkInstallationSetup.java#L130). The JDK directory might not contain the bin/java executable.

After this PR

A JDK directory is considered successfully installed if bin/java exists .
I am also doing a copy to a temporary directory and an atomic move to the destination directory.
A sentinel file is added at the end of a successful installation - I think we might want to use this in the future to check if the jdk was successfully installed or not.

Note: I am not considering for now only the sentinel file to be the source of truth because of backwards compatibility (the jdks we installed so far won't have the sentinel file).

==COMMIT_MSG==
[Fix] JDK is successfully installed if bin/java exists
==COMMIT_MSG==

Possible downsides?

@changelog-app
Copy link

changelog-app bot commented Oct 30, 2024

Generate changelog in changelog/@unreleased

What do the change types mean?
  • feature: A new feature of the service.
  • improvement: An incremental improvement in the functionality or operation of the service.
  • fix: Remedies the incorrect behaviour of a component of the service in a backwards-compatible way.
  • break: Has the potential to break consumers of this service's API, inclusive of both Palantir services
    and external consumers of the service's API (e.g. customer-written software or integrations).
  • deprecation: Advertises the intention to remove service functionality without any change to the
    operation of the service itself.
  • manualTask: Requires the possibility of manual intervention (running a script, eyeballing configuration,
    performing database surgery, ...) at the time of upgrade for it to succeed.
  • migration: A fully automatic upgrade migration task with no engineer input required.

Note: only one type should be chosen.

How are new versions calculated?
  • ❗The break and manual task changelog types will result in a major release!
  • 🐛 The fix changelog type will result in a minor release in most cases, and a patch release version for patch branches. This behaviour is configurable in autorelease.
  • ✨ All others will result in a minor version release.

Type

  • Feature
  • Improvement
  • Fix
  • Break
  • Deprecation
  • Manual task
  • Migration

Description

[Fix] JDK is successfully installed if bin/java or sentinel files exist

Check the box to generate changelog(s)

  • Generate changelog entry

@crogoz crogoz changed the title [Fix] JDK is successfully installed if bin/java exists [Fix] JDK is successfully installed if bin/java or sentinel files exist Oct 30, 2024
@crogoz crogoz marked this pull request as ready for review October 30, 2024 16:03
@crogoz crogoz requested a review from CRogers October 30, 2024 16:07
@crogoz crogoz changed the title [Fix] JDK is successfully installed if bin/java or sentinel files exist [Fix] JDK is successfully installed if bin/java files exist Oct 31, 2024
Comment on lines -163 to +132
echo "Successfully installed JDK distribution in $jdk_installation_directory"
elif [ ! -f "$jdk_installation_directory/bin/java" ]; then
echo "Java executable not found in $jdk_installation_directory/bin/java, re-installing the JDK...."
else
echo "JDK installation $jdk_installation_directory was already configured"
continue
fi
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the github diff is weird, the only changes I have made is adding the if-else conditions to check if the directory and/or bin/java files exists at the top. the rest of the code is unchanged

@@ -153,7 +159,8 @@ private static void writeFileContent(Path path, String content) throws IOExcepti
Files.writeString(path, content + "\n");
}

private void dockerBuildAndRunTestingScript(String baseImage, String shell, boolean installCurl)
private void dockerBuildAndRunTestingScript(
String baseImage, String shell, boolean installCurl, boolean addEmptyGradleJdkDir)
Copy link
Contributor

@CRogers CRogers Oct 31, 2024

Choose a reason for hiding this comment

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

I assumed this meant the ~/.gradle/gradle-jdks dir - maybe call this just addJdkDir?

logger.log("Cannot move the directory to the final directory, attempting to do a non-atomic operation");
Files.move(tempDirWithPrefix, destinationJdkInstallationDirectory, StandardCopyOption.REPLACE_EXISTING);
}
createSentinelFile(destinationJdkInstallationDirectory);
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this sentinel file used for?

Copy link
Contributor

@CRogers CRogers Oct 31, 2024

Choose a reason for hiding this comment

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

I don't think it's used elsewhere in this diff and now we have the atomic move the directory/java binary existing should be enough.

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 am thinking that the sentinel file is the flag that tells us if the installation finished successfully. I was thinking that in the future (if we add the check now , we would re-install jdks that are already correctly installed on user's laptops) we might assume that the installation was successful if the file was created.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would hope that since we move the JDK now it will definitely be fine as the move will mean the directory is either there and correct or not there, rather than just partially copied.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack, I'll remove this then

logger.log(String.format("Distribution URL %s already exists", destinationJdkInstallationDirectory));
return false;
}
logger.log(
String.format("Copying JDK from %s into %s", currentJavaHome, destinationJdkInstallationDirectory));
FileUtils.copyDirectory(currentJavaHome, destinationJdkInstallationDirectory);
Path tempDirWithPrefix = Files.createTempDirectory("gradle-jdks");
Copy link
Contributor

@CRogers CRogers Oct 31, 2024

Choose a reason for hiding this comment

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

Atomic moves generally only work when the source and destination for the filesystem object are on the same filesystem. If they're not it's usually actually a copy. I think here this risks copying to a tmp filesystem, then copying again to the filesystem ~/.gradle/gradle-jdks is mounted on rather than moving to the final destination.

To work around this, I'd make a tmp dir at ~/.gradle/gradle-jdks/tmp and copy it to a subdir in there first before moving. It should definitely be on the same filesystem then.

logger.log(String.format("Distribution URL %s already exists", destinationJdkInstallationDirectory));
return false;
}
logger.log(
String.format("Copying JDK from %s into %s", currentJavaHome, destinationJdkInstallationDirectory));
FileUtils.copyDirectory(currentJavaHome, destinationJdkInstallationDirectory);
Path tempDirWithPrefix = Files.createTempDirectory("gradle-jdks");
Copy link
Contributor

Choose a reason for hiding this comment

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

I would also delete the temp dir if it still exists in a try-finally to make sure it's cleaned even if there's an exception. Don't want an ever increasing number of these.

@@ -65,13 +66,13 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes _attrs) t

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes _attrs) throws IOException {
Files.copy(file, destination.resolve(source.relativize(file)));
Files.copy(file, destination.resolve(source.relativize(file)), StandardCopyOption.REPLACE_EXISTING);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we still need to replace-existing with the copy to a temp location and then move?

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 think it is still better to keep the replace-existing, otherwise if some crash leaves the tmp location un-deleted, then we can recover from it.

"$java_home"/bin/java -cp "$scripts_dir"/gradle-jdks-setup.jar com.palantir.gradle.jdks.setup.GradleJdkInstallationSetup jdkSetup "$jdk_installation_directory" || die "Failed to set up JDK $jdk_installation_directory"
echo "Successfully installed JDK distribution in $jdk_installation_directory"
elif [ ! -f "$jdk_installation_directory/bin/java" ]; then
echo "Java executable not found in $jdk_installation_directory/bin/java, re-installing the JDK...."
Copy link
Contributor

Choose a reason for hiding this comment

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

I think worth having a comment about the possibly broken existing JDKs.

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 file will be added to all the repos (it is used both by the docker images and the gradle jdk enabled repos). Is it OK to mention the possibly broken JDKs in a comment ?

@crogoz crogoz requested a review from CRogers October 31, 2024 13:39
tempCopyDir,
destinationJdkInstallationDirectory,
StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.ATOMIC_MOVE);
Copy link
Contributor

Choose a reason for hiding this comment

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

The common filesystems (ieg APFS/NTFS/ext4) all support atomic moves... but perhaps we should handle the AtomicMoveNotSupportedException like before just incase this ends up on a different filesystem that doesn't?

@bulldozer-bot bulldozer-bot bot merged commit 8114390 into develop Nov 4, 2024
6 checks passed
@bulldozer-bot bulldozer-bot bot deleted the cr/more-sanity-checks-script branch November 4, 2024 16:34
@autorelease3
Copy link

autorelease3 bot commented Nov 4, 2024

Released 0.54.0

@CRogers CRogers mentioned this pull request Nov 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants