Skip to content

Commit

Permalink
Skip restart if cluster was started in single runs, fix #263 (#274)
Browse files Browse the repository at this point in the history
  • Loading branch information
sschnabe authored Feb 22, 2024
1 parent 5b316ea commit 99be815
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 2 deletions.
14 changes: 14 additions & 0 deletions src/main/java/io/kokuwa/maven/k3s/mojo/K3sMojo.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/io/kokuwa/maven/k3s/mojo/RestartMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/kokuwa/maven/k3s/mojo/RunMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ public void execute() throws MojoExecutionException {
// create container

if (create || restart) {

if (create) {
createAndStartK3sContainer();
} else if (restart) {
Expand All @@ -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);
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/io/kokuwa/maven/k3s/util/Marker.java
Original file line number Diff line number Diff line change
@@ -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 [email protected]
* @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);
}
}
}
33 changes: 32 additions & 1 deletion src/test/java/io/kokuwa/maven/k3s/mojo/RestartMojoTest.java
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -53,27 +55,56 @@ 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")
@Test
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");
}

}
17 changes: 16 additions & 1 deletion src/test/java/io/kokuwa/maven/k3s/mojo/RunMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -50,22 +51,26 @@ 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")
@Test
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")
Expand All @@ -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");
}
Expand All @@ -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")
Expand All @@ -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")
Expand All @@ -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");
Expand All @@ -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");
}
}

0 comments on commit 99be815

Please sign in to comment.