Skip to content

Commit

Permalink
fix: link launch dir with existing nucleus package if does not exist
Browse files Browse the repository at this point in the history
  • Loading branch information
alter-mage committed Dec 4, 2024
1 parent 1fc2633 commit 64c2807
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public enum DeploymentErrorCode {
// JVM hashing issue
HASHING_ALGORITHM_UNAVAILABLE(DeploymentErrorType.DEVICE_ERROR),
// Could be a local file issue or a Nucleus issue; we will categorize as the latter for visibility
LAUNCH_DIRECTORY_CORRUPTED(DeploymentErrorType.NUCLEUS_ERROR),
LAUNCH_DIRECTORY_CORRUPTED(DeploymentErrorType.DEVICE_ERROR),

/* Component recipe errors */
RECIPE_PARSE_ERROR(DeploymentErrorType.COMPONENT_RECIPE_ERROR),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,22 @@ public boolean isLaunchDirSetup() {
* @throws DeploymentException when user is not allowed to change file permission
*/
public void validateLaunchDirSetupVerbose() throws DirectoryValidationException, DeploymentException {
Path currentDir = getCurrentDir();
if (!Files.isSymbolicLink(currentDir)) {
throw new DirectoryValidationException("Missing symlink to current nucleus launch directory");
if (!Files.isSymbolicLink(getCurrentDir())) {
try {
/*
Simply recreating a new init dir and relinking the current Nucleus jar path to it should be
sufficient as the kernel update workflow will create the new launch dir and its links anyway
*/
relinkInitLaunchDir(locateCurrentKernelUnpackDir(), true);
} catch (IOException ex) {
throw new DirectoryValidationException("Unable to relink init launch directory", ex);
} catch (URISyntaxException ex) {
// TODO: Fix usage of root path with spaces on linux
throw new DeploymentException("Could not parse init launch directory path", ex);
}
}

Path currentDir = getCurrentDir();
Path loaderPath = getLoaderPathFromLaunchDir(currentDir);
if (Files.exists(loaderPath)) {
if (!loaderPath.toFile().canExecute()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ public DirectoryValidationException(String message) {
super(message);
super.addErrorCode(DeploymentErrorCode.LAUNCH_DIRECTORY_CORRUPTED);
}

public DirectoryValidationException(String message, Throwable throwable) {
super(message, throwable);
super.addErrorCode(DeploymentErrorCode.LAUNCH_DIRECTORY_CORRUPTED);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void GIVEN_launch_dir_corrupted_WHEN_deployment_activate_THEN_deployment_fail(Ex
assertEquals(mockException, result.getFailureCause().getCause());

List<String> expectedStack = Arrays.asList("DEPLOYMENT_FAILURE", "LAUNCH_DIRECTORY_CORRUPTED");
List<String> expectedTypes = Collections.singletonList("NUCLEUS_ERROR");
List<String> expectedTypes = Collections.singletonList("DEVICE_ERROR");
TestUtils.validateGenerateErrorReport(result.getFailureCause(), expectedStack, expectedTypes);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.aws.greengrass.config.PlatformResolver;
import com.aws.greengrass.deployment.DeploymentDirectoryManager;
import com.aws.greengrass.deployment.bootstrap.BootstrapManager;
import com.aws.greengrass.lifecyclemanager.exceptions.DirectoryValidationException;
import com.aws.greengrass.testcommons.testutilities.GGExtension;
import com.aws.greengrass.util.NucleusPaths;
import com.aws.greengrass.util.Utils;
Expand All @@ -19,6 +20,7 @@
import org.mockito.junit.jupiter.MockitoExtension;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;

Expand All @@ -34,9 +36,13 @@
import static org.hamcrest.io.FileMatchers.anExistingFileOrDirectory;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.internal.verification.VerificationModeFactory.times;
Expand Down Expand Up @@ -212,6 +218,38 @@ void GIVEN_launch_params_THEN_write_to_file() throws Exception {
assertEquals("mock string", new String(Files.readAllBytes(expectedLaunchParamsPath)));
}

@Test
void GIVEN_validate_launch_dir_setup_WHEN_current_link_missing_and_exception_THEN_directory_validation_exception() throws IOException {
// GIVEN
Path outsidePath = createRandomDirectory();
Path unpackPath = createRandomDirectory();
Files.createDirectories(unpackPath.resolve("bin"));
String loaderName = "loader";
if (PlatformResolver.isWindows) {
loaderName = "loader.cmd";
}
Files.createFile(unpackPath.resolve("bin").resolve(loaderName));

Path distroPath = kernelAlternatives.getInitDir().resolve(KERNEL_DISTRIBUTION_DIR);
Files.createDirectories(kernelAlternatives.getInitDir());
// current -> init
kernelAlternatives.setupLinkToDirectory(kernelAlternatives.getCurrentDir(), kernelAlternatives.getInitDir());
// init/distro -> outsidePath
kernelAlternatives.setupLinkToDirectory(distroPath, outsidePath);
assertEquals(kernelAlternatives.getInitDir(), Files.readSymbolicLink(kernelAlternatives.getCurrentDir()));
assertEquals(outsidePath, Files.readSymbolicLink(distroPath));

// WHEN
Files.deleteIfExists(kernelAlternatives.getCurrentDir());
lenient().doThrow(new IOException("Random test failure"))
.when(kernelAlternatives).relinkInitLaunchDir(any(Path.class), eq(true));

// THEN
DirectoryValidationException ex = assertThrows(DirectoryValidationException.class,
() -> kernelAlternatives.validateLaunchDirSetupVerbose());
assertEquals(ex.getMessage(), "Unable to relink init launch directory");
}

private Path createRandomDirectory() throws IOException {
Path path = altsDir.resolve(Utils.generateRandomString(4));
Utils.createPaths(path);
Expand Down

0 comments on commit 64c2807

Please sign in to comment.