diff --git a/src/main/java/io/kokuwa/maven/k3s/mojo/K3sMojo.java b/src/main/java/io/kokuwa/maven/k3s/mojo/K3sMojo.java index 47c4568..38d287b 100644 --- a/src/main/java/io/kokuwa/maven/k3s/mojo/K3sMojo.java +++ b/src/main/java/io/kokuwa/maven/k3s/mojo/K3sMojo.java @@ -1,5 +1,6 @@ package io.kokuwa.maven.k3s.mojo; +import java.io.File; import java.nio.file.Path; import org.apache.maven.plugin.AbstractMojo; @@ -8,6 +9,7 @@ import io.kokuwa.maven.k3s.util.DebugLog; import io.kokuwa.maven.k3s.util.Docker; +import io.kokuwa.maven.k3s.util.Marker; /** * Base class for all mojos of this plugin. @@ -41,6 +43,10 @@ public abstract class K3sMojo extends AbstractMojo { @Parameter(defaultValue = "k3s-maven-plugin", readonly = true) private String volumeName; + /** Marker for maven status stuff. */ + @Parameter(defaultValue = "${project.build.directory}/maven-status/k3s-maven-plugin", readonly = true) + private Marker marker; + // generic methods private Log log; @@ -50,6 +56,10 @@ public boolean isSkip(boolean skipMojo) { return skip || skipMojo; } + public Marker getMarker() { + return marker; + } + @Override public Log getLog() { return log == null ? log = new DebugLog(super.getLog(), debug) : log; @@ -66,6 +76,10 @@ public String toLinuxPath(Path path) { // setter + public void setMarker(File directory) { + this.marker = new Marker(directory); + } + public void setDebug(boolean debug) { this.debug = debug; } diff --git a/src/main/java/io/kokuwa/maven/k3s/mojo/RestartMojo.java b/src/main/java/io/kokuwa/maven/k3s/mojo/RestartMojo.java index d88d6aa..b190202 100644 --- a/src/main/java/io/kokuwa/maven/k3s/mojo/RestartMojo.java +++ b/src/main/java/io/kokuwa/maven/k3s/mojo/RestartMojo.java @@ -67,6 +67,12 @@ public void execute() throws MojoExecutionException { return; } + // check marker, if marker is found skip restart + + if (getMarker().consumeStarted()) { + return; + } + // skip if no resources configured if (resources.isEmpty()) { diff --git a/src/main/java/io/kokuwa/maven/k3s/mojo/RunMojo.java b/src/main/java/io/kokuwa/maven/k3s/mojo/RunMojo.java index a43c0c0..bd67ca4 100644 --- a/src/main/java/io/kokuwa/maven/k3s/mojo/RunMojo.java +++ b/src/main/java/io/kokuwa/maven/k3s/mojo/RunMojo.java @@ -236,6 +236,7 @@ public void execute() throws MojoExecutionException { // create container if (create || restart) { + if (create) { createAndStartK3sContainer(); } else if (restart) { @@ -246,6 +247,10 @@ public void execute() throws MojoExecutionException { var await = Await.await(getLog(), "k3s api available").timeout(nodeTimeout); getDocker().waitForLog(await, output -> output.stream().anyMatch(l -> l.contains("k3s is up and running"))); + + // write file that k3s started + + getMarker().writeStarted(); } getDocker().copyFromContainer("/etc/rancher/k3s/k3s.yaml", kubeconfig); diff --git a/src/main/java/io/kokuwa/maven/k3s/util/Marker.java b/src/main/java/io/kokuwa/maven/k3s/util/Marker.java new file mode 100644 index 0000000..4c0c46a --- /dev/null +++ b/src/main/java/io/kokuwa/maven/k3s/util/Marker.java @@ -0,0 +1,40 @@ +package io.kokuwa.maven.k3s.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.maven.plugin.MojoExecutionException; + +/** + * Class to handle markers as communication between mojo executions. + * + * @author stephan.schnabel@posteo.de + * @since 1.3.0 + */ +public class Marker { + + private final Path startedMarker; + + public Marker(File directory) { + this.startedMarker = directory.toPath().resolve("started"); + } + + public void writeStarted() throws MojoExecutionException { + try { + Files.createDirectories(startedMarker.getParent()); + Files.write(startedMarker, new byte[0]); + } catch (IOException e) { + throw new MojoExecutionException("Failed to write marker to " + startedMarker, e); + } + } + + public boolean consumeStarted() throws MojoExecutionException { + try { + return Files.deleteIfExists(startedMarker); + } catch (IOException e) { + throw new MojoExecutionException("Failed to delete marker at " + startedMarker, e); + } + } +} diff --git a/src/test/java/io/kokuwa/maven/k3s/mojo/RestartMojoTest.java b/src/test/java/io/kokuwa/maven/k3s/mojo/RestartMojoTest.java index a416365..48a666b 100644 --- a/src/test/java/io/kokuwa/maven/k3s/mojo/RestartMojoTest.java +++ b/src/test/java/io/kokuwa/maven/k3s/mojo/RestartMojoTest.java @@ -1,7 +1,9 @@ package io.kokuwa.maven.k3s.mojo; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; @@ -53,20 +55,29 @@ void withoutResources(RestartMojo restartMojo) { @Test void invalid(RunMojo runMojo, RestartMojo restartMojo) { assertDoesNotThrow(runMojo::execute); + assertTrue(assertDoesNotThrow(runMojo.getMarker()::consumeStarted), "started marker expected"); restartMojo.setResources(List.of("pod/nope")); assertThrowsExactly(MojoExecutionException.class, restartMojo::execute, () -> "No k3s container found"); restartMojo.setResources(List.of("deployment/nope/nope")); assertThrowsExactly(MojoExecutionException.class, restartMojo::execute, () -> "No k3s container found"); } - @DisplayName("with statefulset") + @DisplayName("with statefulset and started") @Test void statefulset(RunMojo runMojo, ApplyMojo applyMojo, RestartMojo restartMojo) { + applyMojo.setSubdir("statefulset"); restartMojo.setResources(List.of("statefulset/echo")); assertDoesNotThrow(runMojo::execute); + assertTrue(assertDoesNotThrow(runMojo.getMarker()::consumeStarted), "started marker expected"); assertDoesNotThrow(applyMojo::execute); + + // with restart mojo should take some time + + var started = System.currentTimeMillis(); assertDoesNotThrow(restartMojo::execute); + var duration = System.currentTimeMillis() - started; + assertTrue(duration > 100, "restart did not happend"); } @DisplayName("with not existing resource") @@ -74,6 +85,26 @@ void statefulset(RunMojo runMojo, ApplyMojo applyMojo, RestartMojo restartMojo) void notExisting(RunMojo runMojo, RestartMojo restartMojo) { restartMojo.setResources(List.of("statefulset/echo")); assertDoesNotThrow(runMojo::execute); + assertTrue(assertDoesNotThrow(runMojo.getMarker()::consumeStarted), "started marker expected"); assertThrowsExactly(MojoExecutionException.class, restartMojo::execute, () -> "Failed to restart resources"); } + + @DisplayName("with marker start") + @Test + void withMarker(RunMojo runMojo, ApplyMojo applyMojo, RestartMojo restartMojo) { + + applyMojo.setSubdir("statefulset"); + restartMojo.setResources(List.of("statefulset/echo")); + assertDoesNotThrow(runMojo::execute); + assertDoesNotThrow(applyMojo::execute); + + // without restart mojo should immediately return + + var started = System.currentTimeMillis(); + assertDoesNotThrow(restartMojo::execute); + var duration = System.currentTimeMillis() - started; + assertTrue(duration < 10, "restart did happend"); + assertFalse(assertDoesNotThrow(runMojo.getMarker()::consumeStarted), "no started marker expected"); + } + } diff --git a/src/test/java/io/kokuwa/maven/k3s/mojo/RunMojoTest.java b/src/test/java/io/kokuwa/maven/k3s/mojo/RunMojoTest.java index d47442f..4a81cef 100644 --- a/src/test/java/io/kokuwa/maven/k3s/mojo/RunMojoTest.java +++ b/src/test/java/io/kokuwa/maven/k3s/mojo/RunMojoTest.java @@ -6,6 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; @@ -50,10 +51,12 @@ void withSkip(RunMojo runMojo) throws MojoExecutionException { void withFailIfExists(RunMojo runMojo) throws MojoExecutionException { runMojo.setFailIfExists(true); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); var expectedMessage = "Container with id '" + docker.getContainer().get().id + "' found. Please remove that container or set 'k3s.failIfExists' to false."; var actualMessage = assertThrows(MojoExecutionException.class, runMojo::execute).getMessage(); assertEquals(expectedMessage, actualMessage, "exception message"); + assertFalse(runMojo.getMarker().consumeStarted(), "no started marker expected"); } @DisplayName("with fail on existing container that is stopped") @@ -61,11 +64,13 @@ void withFailIfExists(RunMojo runMojo) throws MojoExecutionException { void withFailIfExistsStopped(RunMojo runMojo, Log log) throws MojoExecutionException { runMojo.setFailIfExists(true); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); Task.of(log, "docker", "stop", "k3s-maven-plugin").run(); var expectedMessage = "Container with id '" + docker.getContainer().get().id + "' found. Please remove that container or set 'k3s.failIfExists' to false."; var actualMessage = assertThrows(MojoExecutionException.class, runMojo::execute).getMessage(); assertEquals(expectedMessage, actualMessage, "exception message"); + assertFalse(runMojo.getMarker().consumeStarted(), "no started marker expected"); } @DisplayName("with replace on existing container") @@ -74,8 +79,10 @@ void withReplaceIfExists(RunMojo runMojo) throws MojoExecutionException { runMojo.setFailIfExists(false); runMojo.setReplaceIfExists(true); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); var containerBefore = docker.getContainer().orElseThrow(); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); var containerAfter = docker.getContainer().orElseThrow(); assertNotEquals(containerBefore.id, containerAfter.id, "container was not replaced"); } @@ -86,11 +93,13 @@ void withReplaceIfExistsStopped(RunMojo runMojo, Log log) throws MojoExecutionEx runMojo.setFailIfExists(false); runMojo.setReplaceIfExists(true); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); var containerBefore = docker.getContainer().orElseThrow(); Task.of(log, "docker", "stop", "k3s-maven-plugin").run(); assertDoesNotThrow(runMojo::execute); var containerAfter = docker.getContainer().orElseThrow(); assertNotEquals(containerBefore.id, containerAfter.id, "container was not replaced"); + assertTrue(runMojo.getMarker().consumeStarted()); } @DisplayName("without fail on existing container") @@ -99,10 +108,12 @@ void withoutFailIfExists(RunMojo runMojo) throws MojoExecutionException { runMojo.setFailIfExists(false); runMojo.setReplaceIfExists(false); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); var containerBefore = docker.getContainer().orElseThrow(); assertDoesNotThrow(runMojo::execute); var containerAfter = docker.getContainer().orElseThrow(); assertEquals(containerBefore.id, containerAfter.id, "container shouldn't be replaced"); + assertFalse(runMojo.getMarker().consumeStarted(), "no started marker expected"); } @DisplayName("without fail on existing container that is stopped") @@ -111,9 +122,11 @@ void withoutFailIfExistsStopped(RunMojo runMojo, Log log, ApplyMojo applyMojo) t runMojo.setFailIfExists(false); runMojo.setReplaceIfExists(false); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); var containerBefore = docker.getContainer().orElseThrow(); Task.of(log, "docker", "stop", "k3s-maven-plugin").run(); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); assertDoesNotThrow(applyMojo::execute); var containerAfter = docker.getContainer().orElseThrow(); assertEquals(containerBefore.id, containerAfter.id, "container shouldn't be replaced"); @@ -124,16 +137,18 @@ void withoutFailIfExistsStopped(RunMojo runMojo, Log log, ApplyMojo applyMojo) t void withRegistries(RunMojo runMojo, Log log) throws MojoExecutionException { runMojo.setRegistries(new File("src/test/resources/registries.yaml")); assertDoesNotThrow(runMojo::execute); + assertTrue(runMojo.getMarker().consumeStarted(), "started marker expected"); docker.waitForLog(Await.await(log, "registries.yaml used"), logs -> logs.stream() .anyMatch(l -> l.contains("Using private registry config file at /etc/rancher/k3s/registries.yaml"))); } @DisplayName("with custom registries.yaml (missing)") @Test - void withRegistriesMissing(RunMojo runMojo) { + void withRegistriesMissing(RunMojo runMojo) throws MojoExecutionException { var file = new File("src/test/resources/nope.yaml"); runMojo.setRegistries(file); var actualMessage = assertThrowsExactly(MojoExecutionException.class, runMojo::execute).getMessage(); assertEquals("Registries file '" + file.getAbsolutePath() + "' not found.", actualMessage, "exception message"); + assertFalse(runMojo.getMarker().consumeStarted(), "no started marker expected"); } }