diff --git a/handler/src/main/java/io/jeyong/handler/ApplicationTerminator.java b/handler/src/main/java/io/jeyong/handler/ApplicationTerminator.java index e33d0bc..97d56dd 100644 --- a/handler/src/main/java/io/jeyong/handler/ApplicationTerminator.java +++ b/handler/src/main/java/io/jeyong/handler/ApplicationTerminator.java @@ -18,11 +18,15 @@ protected ApplicationTerminator(final String terminationMessagePath, final Strin public SignalHandler handleTermination() { return signal -> { - logger.info("Received SIGTERM signal. Initiating termination handler."); + logTerminationSignal(signal.getName()); FileUtils.writeToFile(terminationMessagePath, terminationMessage); System.exit(getExitCode()); }; } + private void logTerminationSignal(final String signalName) { + logger.info("Received {} signal. Initiating termination handler.", signalName); + } + protected abstract int getExitCode(); } diff --git a/handler/src/main/java/io/jeyong/handler/FileUtils.java b/handler/src/main/java/io/jeyong/handler/FileUtils.java index b8007f1..b89bec3 100644 --- a/handler/src/main/java/io/jeyong/handler/FileUtils.java +++ b/handler/src/main/java/io/jeyong/handler/FileUtils.java @@ -7,7 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class FileUtils { +public final class FileUtils { private static final Logger logger = LoggerFactory.getLogger(FileUtils.class); diff --git a/handler/src/main/java/io/jeyong/handler/SignalHandlerRegistrar.java b/handler/src/main/java/io/jeyong/handler/SignalHandlerRegistrar.java index 569abff..08a6a02 100644 --- a/handler/src/main/java/io/jeyong/handler/SignalHandlerRegistrar.java +++ b/handler/src/main/java/io/jeyong/handler/SignalHandlerRegistrar.java @@ -1,9 +1,10 @@ package io.jeyong.handler; -import jakarta.annotation.PostConstruct; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.EventListener; import sun.misc.Signal; -public class SignalHandlerRegistrar { +public final class SignalHandlerRegistrar { private final ApplicationTerminator applicationTerminator; private final String signalType; @@ -13,7 +14,7 @@ public SignalHandlerRegistrar(final ApplicationTerminator applicationTerminator, this.signalType = signalType; } - @PostConstruct + @EventListener(ContextRefreshedEvent.class) public void registerHandler() { Signal.handle(new Signal(signalType), applicationTerminator.handleTermination()); } diff --git a/handler/src/main/java/io/jeyong/handler/SigtermHandlerProperties.java b/handler/src/main/java/io/jeyong/handler/SigtermHandlerProperties.java index 5fa0bbd..f5812e8 100644 --- a/handler/src/main/java/io/jeyong/handler/SigtermHandlerProperties.java +++ b/handler/src/main/java/io/jeyong/handler/SigtermHandlerProperties.java @@ -51,7 +51,10 @@ */ // @formatter:on @ConfigurationProperties(prefix = "kubernetes.sigterm-handler") -public class SigtermHandlerProperties { +public final class SigtermHandlerProperties { + + private static final int MIN_EXIT_CODE = 0; + private static final int MAX_EXIT_CODE = 255; private boolean enabled = true; private int exitCode = 0; @@ -71,6 +74,7 @@ public int getExitCode() { } public void setExitCode(final int exitCode) { + validateExitCode(exitCode); this.exitCode = exitCode; } @@ -89,4 +93,18 @@ public String getTerminationMessage() { public void setTerminationMessage(final String terminationMessage) { this.terminationMessage = terminationMessage; } + + /** + * Validates the exit code to ensure it adheres to the POSIX standard. + * + * @param exitCode the exit code to validate + * @throws IllegalArgumentException if the exit code is outside the valid range + */ + private void validateExitCode(final int exitCode) { + if (exitCode < MIN_EXIT_CODE || exitCode > MAX_EXIT_CODE) { + throw new IllegalArgumentException( + String.format("Exit code must be between %d and %d (inclusive) as per POSIX standard.", + MIN_EXIT_CODE, MAX_EXIT_CODE)); + } + } } diff --git a/handler/src/main/java/io/jeyong/handler/SpringContextTerminator.java b/handler/src/main/java/io/jeyong/handler/SpringContextTerminator.java index 3053305..0562f08 100644 --- a/handler/src/main/java/io/jeyong/handler/SpringContextTerminator.java +++ b/handler/src/main/java/io/jeyong/handler/SpringContextTerminator.java @@ -3,7 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.context.ApplicationContext; -public class SpringContextTerminator extends ApplicationTerminator { +public final class SpringContextTerminator extends ApplicationTerminator { private final ApplicationContext applicationContext; private final int exitCode; diff --git a/test/src/test/java/io/jeyong/test/unit/ApplicationTerminatorTest.java b/test/src/test/java/io/jeyong/test/unit/ApplicationTerminatorTest.java index 0b15005..02a5598 100644 --- a/test/src/test/java/io/jeyong/test/unit/ApplicationTerminatorTest.java +++ b/test/src/test/java/io/jeyong/test/unit/ApplicationTerminatorTest.java @@ -8,6 +8,7 @@ import java.nio.file.Files; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import sun.misc.Signal; import sun.misc.SignalHandler; @DisplayName("ApplicationTerminator Unit Test") @@ -30,7 +31,7 @@ protected int getExitCode() { }; // when - catchSystemExit(() -> terminator.handleTermination().handle(null)); + catchSystemExit(() -> terminator.handleTermination().handle(new Signal("TERM"))); // then assertThat(Files.readString(tempFile.toPath())).isEqualTo(expectedMessage); @@ -54,7 +55,7 @@ protected int getExitCode() { SignalHandler handler = terminator.handleTermination(); // when - int actualExitCode = catchSystemExit(() -> handler.handle(null)); + int actualExitCode = catchSystemExit(() -> handler.handle(new Signal("TERM"))); // then assertThat(actualExitCode).isEqualTo(expectedExitCode);