mirror of
https://github.com/corda/corda.git
synced 2024-12-21 05:53:23 +00:00
Re enabling persistent volume claims (#5628)
* TM-68 reenabling persistent volume claims using azure files * TM-68 jenkins stackstracee * TM-68 removing duplicate volume * TM-68 pushing storage class yaml file * TM-68 writing all results to the new persistent volume * TM-68 fix wrong directory * TM-68 fix wrong directory * reapply lost merge commit * investigate missing POD from test results * more investigations around pods not executing their tests * make Pod command line more strict with regards to sub command failure * make logs an artifact within jenkins * tidy up command line
This commit is contained in:
parent
f9890a5359
commit
d5462a2afe
8
.ci/dev/azureStorageClass.yml
Normal file
8
.ci/dev/azureStorageClass.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
kind: StorageClass
|
||||||
|
apiVersion: storage.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: testing-storage
|
||||||
|
provisioner: kubernetes.io/azure-file
|
||||||
|
parameters:
|
||||||
|
storageAccount: testrestart
|
||||||
|
location: westeurope
|
1
Jenkinsfile
vendored
1
Jenkinsfile
vendored
@ -57,6 +57,7 @@ pipeline {
|
|||||||
|
|
||||||
post {
|
post {
|
||||||
always {
|
always {
|
||||||
|
archiveArtifacts artifacts: '**/pod-logs/**/*.log', fingerprint: false
|
||||||
junit '**/build/test-results-xml/**/*.xml'
|
junit '**/build/test-results-xml/**/*.xml'
|
||||||
}
|
}
|
||||||
cleanup {
|
cleanup {
|
||||||
|
@ -176,55 +176,47 @@ class DistributedTesting implements Plugin<Project> {
|
|||||||
|
|
||||||
private Test modifyTestTaskForParallelExecution(Project subProject, Test task, BucketingAllocatorTask globalAllocator) {
|
private Test modifyTestTaskForParallelExecution(Project subProject, Test task, BucketingAllocatorTask globalAllocator) {
|
||||||
subProject.logger.info("modifying task: ${task.getPath()} to depend on task ${globalAllocator.getPath()}")
|
subProject.logger.info("modifying task: ${task.getPath()} to depend on task ${globalAllocator.getPath()}")
|
||||||
def reportsDir = new File(new File(subProject.rootProject.getBuildDir(), "test-reports"), subProject.name + "-" + task.name)
|
def reportsDir = new File(new File(KubesTest.TEST_RUN_DIR, "test-reports"), subProject.name + "-" + task.name)
|
||||||
|
reportsDir.mkdirs()
|
||||||
|
File executedTestsFile = new File(KubesTest.TEST_RUN_DIR + "/executedTests.txt")
|
||||||
task.configure {
|
task.configure {
|
||||||
dependsOn globalAllocator
|
dependsOn globalAllocator
|
||||||
binResultsDir new File(reportsDir, "binary")
|
binResultsDir new File(reportsDir, "binary")
|
||||||
reports.junitXml.destination new File(reportsDir, "xml")
|
reports.junitXml.destination new File(reportsDir, "xml")
|
||||||
maxHeapSize = "6g"
|
maxHeapSize = "10g"
|
||||||
|
|
||||||
doFirst {
|
doFirst {
|
||||||
filter {
|
|
||||||
List<String> executedTests = []
|
|
||||||
File executedTestsFile = new File(KubesTest.TEST_RUN_DIR + "/executedTests.txt")
|
|
||||||
try {
|
|
||||||
executedTests = executedTestsFile.readLines()
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
executedTestsFile.createNewFile()
|
executedTestsFile.createNewFile()
|
||||||
}
|
filter {
|
||||||
|
List<String> executedTests = executedTestsFile.readLines()
|
||||||
task.afterTest { desc, result ->
|
|
||||||
executedTestsFile.withWriterAppend { writer ->
|
|
||||||
writer.writeLine(desc.getClassName() + "." + desc.getName())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def fork = getPropertyAsInt(subProject, "dockerFork", 0)
|
def fork = getPropertyAsInt(subProject, "dockerFork", 0)
|
||||||
subProject.logger.info("requesting tests to include in testing task ${task.getPath()} (idx: ${fork})")
|
subProject.logger.info("requesting tests to include in testing task ${task.getPath()} (idx: ${fork})")
|
||||||
List<String> includes = globalAllocator.getTestIncludesForForkAndTestTask(
|
List<String> includes = globalAllocator.getTestIncludesForForkAndTestTask(
|
||||||
fork,
|
fork,
|
||||||
task)
|
task)
|
||||||
subProject.logger.info "got ${includes.size()} tests to include into testing task ${task.getPath()}"
|
subProject.logger.info "got ${includes.size()} tests to include into testing task ${task.getPath()}"
|
||||||
|
|
||||||
if (includes.size() == 0) {
|
if (includes.size() == 0) {
|
||||||
subProject.logger.info "Disabling test execution for testing task ${task.getPath()}"
|
subProject.logger.info "Disabling test execution for testing task ${task.getPath()}"
|
||||||
excludeTestsMatching "*"
|
excludeTestsMatching "*"
|
||||||
}
|
}
|
||||||
|
|
||||||
includes.removeAll(executedTests)
|
includes.removeAll(executedTests)
|
||||||
|
|
||||||
executedTests.forEach { exclude ->
|
executedTests.forEach { exclude ->
|
||||||
subProject.logger.info "excluding: $exclude for testing task ${task.getPath()}"
|
subProject.logger.info "excluding: $exclude for testing task ${task.getPath()}"
|
||||||
excludeTestsMatching exclude
|
excludeTestsMatching exclude
|
||||||
}
|
}
|
||||||
|
|
||||||
includes.forEach { include ->
|
includes.forEach { include ->
|
||||||
subProject.logger.info "including: $include for testing task ${task.getPath()}"
|
subProject.logger.info "including: $include for testing task ${task.getPath()}"
|
||||||
includeTestsMatching include
|
includeTestsMatching include
|
||||||
}
|
}
|
||||||
|
|
||||||
failOnNoMatchingTests false
|
failOnNoMatchingTests false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterTest { desc, result ->
|
||||||
|
executedTestsFile.withWriterAppend { writer ->
|
||||||
|
writer.writeLine(desc.getClassName() + "." + desc.getName())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return task
|
return task
|
||||||
|
@ -18,6 +18,7 @@ import io.fabric8.kubernetes.client.dsl.PodResource;
|
|||||||
import io.fabric8.kubernetes.client.utils.Serialization;
|
import io.fabric8.kubernetes.client.utils.Serialization;
|
||||||
import net.corda.testing.retry.Retry;
|
import net.corda.testing.retry.Retry;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
import org.gradle.api.DefaultTask;
|
import org.gradle.api.DefaultTask;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -26,6 +27,8 @@ import java.io.BufferedReader;
|
|||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -150,7 +153,8 @@ public class KubesTest extends DefaultTask {
|
|||||||
int numberOfRetries
|
int numberOfRetries
|
||||||
) {
|
) {
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
return buildRunPodWithRetriesOrThrow(namespace, numberOfPods, podIdx, podName, printOutput, numberOfRetries);
|
PersistentVolumeClaim pvc = createPvc(podName);
|
||||||
|
return buildRunPodWithRetriesOrThrow(namespace, numberOfPods, podIdx, podName, printOutput, numberOfRetries, pvc);
|
||||||
}, executorService);
|
}, executorService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,20 +162,26 @@ public class KubesTest extends DefaultTask {
|
|||||||
Runtime.getRuntime().addShutdownHook(new Thread(hook));
|
Runtime.getRuntime().addShutdownHook(new Thread(hook));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PersistentVolumeClaim createPvc(KubernetesClient client, String name) {
|
private PersistentVolumeClaim createPvc(String name) {
|
||||||
PersistentVolumeClaim pvc = client.persistentVolumeClaims()
|
PersistentVolumeClaim pvc;
|
||||||
|
try (KubernetesClient client = getKubernetesClient()) {
|
||||||
|
pvc = client.persistentVolumeClaims()
|
||||||
.inNamespace(NAMESPACE)
|
.inNamespace(NAMESPACE)
|
||||||
.createNew()
|
.createNew()
|
||||||
.editOrNewMetadata().withName(name).endMetadata()
|
.editOrNewMetadata().withName(name).endMetadata()
|
||||||
.editOrNewSpec()
|
.editOrNewSpec()
|
||||||
.withAccessModes("ReadWriteOnce")
|
.withAccessModes("ReadWriteOnce")
|
||||||
.editOrNewResources().addToRequests("storage", new Quantity("100Mi")).endResources()
|
.editOrNewResources().addToRequests("storage", new Quantity("100Mi")).endResources()
|
||||||
|
.withStorageClassName("testing-storage")
|
||||||
.endSpec()
|
.endSpec()
|
||||||
.done();
|
.done();
|
||||||
|
}
|
||||||
|
|
||||||
addShutdownHook(() -> {
|
addShutdownHook(() -> {
|
||||||
|
try (KubernetesClient client = getKubernetesClient()) {
|
||||||
System.out.println("Deleting PVC: " + pvc.getMetadata().getName());
|
System.out.println("Deleting PVC: " + pvc.getMetadata().getName());
|
||||||
client.persistentVolumeClaims().delete(pvc);
|
client.persistentVolumeClaims().delete(pvc);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return pvc;
|
return pvc;
|
||||||
}
|
}
|
||||||
@ -182,8 +192,8 @@ public class KubesTest extends DefaultTask {
|
|||||||
int podIdx,
|
int podIdx,
|
||||||
String podName,
|
String podName,
|
||||||
boolean printOutput,
|
boolean printOutput,
|
||||||
int numberOfRetries
|
int numberOfRetries,
|
||||||
) {
|
PersistentVolumeClaim pvc) {
|
||||||
addShutdownHook(() -> {
|
addShutdownHook(() -> {
|
||||||
System.out.println("deleting pod: " + podName);
|
System.out.println("deleting pod: " + podName);
|
||||||
try (KubernetesClient client = getKubernetesClient()) {
|
try (KubernetesClient client = getKubernetesClient()) {
|
||||||
@ -207,7 +217,7 @@ public class KubesTest extends DefaultTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
getProject().getLogger().lifecycle("creating pod: " + podName);
|
getProject().getLogger().lifecycle("creating pod: " + podName);
|
||||||
createdPod = client.pods().inNamespace(namespace).create(buildPodRequest(podName));
|
createdPod = client.pods().inNamespace(namespace).create(buildPodRequest(podName, pvc));
|
||||||
getProject().getLogger().lifecycle("scheduled pod: " + podName);
|
getProject().getLogger().lifecycle("scheduled pod: " + podName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,12 +231,22 @@ public class KubesTest extends DefaultTask {
|
|||||||
CompletableFuture<Integer> waiter = new CompletableFuture<>();
|
CompletableFuture<Integer> waiter = new CompletableFuture<>();
|
||||||
File podOutput = executeBuild(namespace, numberOfPods, podIdx, podName, printOutput, stdOutOs, stdOutIs, errChannelStream, waiter);
|
File podOutput = executeBuild(namespace, numberOfPods, podIdx, podName, printOutput, stdOutOs, stdOutIs, errChannelStream, waiter);
|
||||||
|
|
||||||
|
|
||||||
int resCode = waiter.join();
|
int resCode = waiter.join();
|
||||||
getProject().getLogger().lifecycle("build has ended on on pod " + podName + " (" + podIdx + "/" + numberOfPods + "), gathering results");
|
getProject().getLogger().lifecycle("build has ended on on pod " + podName + " (" + podIdx + "/" + numberOfPods + ") with result " + resCode + " , gathering results");
|
||||||
Collection<File> binaryResults = downloadTestXmlFromPod(namespace, createdPod);
|
Collection<File> binaryResults = downloadTestXmlFromPod(namespace, createdPod);
|
||||||
getLogger().lifecycle("removing pod " + podName + " (" + podIdx + "/" + numberOfPods + ") after completed build");
|
getLogger().lifecycle("removing pod " + podName + " (" + podIdx + "/" + numberOfPods + ") after completed build");
|
||||||
|
File podLogsDirectory = new File(getProject().getBuildDir(), "pod-logs");
|
||||||
|
if (!podLogsDirectory.exists()) {
|
||||||
|
podLogsDirectory.mkdirs();
|
||||||
|
}
|
||||||
|
File logFileToArchive = new File(podLogsDirectory, podName + ".log");
|
||||||
|
try (FileInputStream logIn = new FileInputStream(podOutput); FileOutputStream logOut = new FileOutputStream(logFileToArchive)) {
|
||||||
|
IOUtils.copy(logIn, logOut);
|
||||||
|
}
|
||||||
try (KubernetesClient client = getKubernetesClient()) {
|
try (KubernetesClient client = getKubernetesClient()) {
|
||||||
client.pods().delete(createdPod);
|
client.pods().delete(createdPod);
|
||||||
|
client.persistentVolumeClaims().delete(pvc);
|
||||||
}
|
}
|
||||||
return new KubePodResult(resCode, podOutput, binaryResults);
|
return new KubePodResult(resCode, podOutput, binaryResults);
|
||||||
});
|
});
|
||||||
@ -246,7 +266,7 @@ public class KubesTest extends DefaultTask {
|
|||||||
ByteArrayOutputStream errChannelStream,
|
ByteArrayOutputStream errChannelStream,
|
||||||
CompletableFuture<Integer> waiter) throws IOException {
|
CompletableFuture<Integer> waiter) throws IOException {
|
||||||
KubernetesClient client = getKubernetesClient();
|
KubernetesClient client = getKubernetesClient();
|
||||||
ExecListener execListener = buildExecListenerForPod(podName, errChannelStream, waiter);
|
ExecListener execListener = buildExecListenerForPod(podName, errChannelStream, waiter, client);
|
||||||
stdOutIs.connect(stdOutOs);
|
stdOutIs.connect(stdOutOs);
|
||||||
|
|
||||||
String[] buildCommand = getBuildCommand(numberOfPods, podIdx);
|
String[] buildCommand = getBuildCommand(numberOfPods, podIdx);
|
||||||
@ -260,7 +280,7 @@ public class KubesTest extends DefaultTask {
|
|||||||
return startLogPumping(stdOutIs, podIdx, printOutput);
|
return startLogPumping(stdOutIs, podIdx, printOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pod buildPodRequest(String podName) {
|
private Pod buildPodRequest(String podName, PersistentVolumeClaim pvc) {
|
||||||
return new PodBuilder()
|
return new PodBuilder()
|
||||||
.withNewMetadata().withName(podName).endMetadata()
|
.withNewMetadata().withName(podName).endMetadata()
|
||||||
|
|
||||||
@ -273,23 +293,12 @@ public class KubesTest extends DefaultTask {
|
|||||||
.withPath("/tmp/gradle")
|
.withPath("/tmp/gradle")
|
||||||
.endHostPath()
|
.endHostPath()
|
||||||
.endVolume()
|
.endVolume()
|
||||||
|
|
||||||
.addNewVolume()
|
.addNewVolume()
|
||||||
.withName("testruns")
|
.withName("testruns")
|
||||||
.withNewHostPath()
|
.withNewPersistentVolumeClaim()
|
||||||
.withType("DirectoryOrCreate")
|
.withClaimName(pvc.getMetadata().getName())
|
||||||
.withPath("/tmp/testruns")
|
.endPersistentVolumeClaim()
|
||||||
.endHostPath()
|
|
||||||
.endVolume()
|
.endVolume()
|
||||||
|
|
||||||
|
|
||||||
// .addNewVolume()
|
|
||||||
// .withName("testruns")
|
|
||||||
// .withNewPersistentVolumeClaim()
|
|
||||||
// .withClaimName(pvc.getMetadata().getName())
|
|
||||||
// .endPersistentVolumeClaim()
|
|
||||||
// .endVolume()
|
|
||||||
|
|
||||||
.addNewContainer()
|
.addNewContainer()
|
||||||
.withImage(dockerTag)
|
.withImage(dockerTag)
|
||||||
.withCommand("bash")
|
.withCommand("bash")
|
||||||
@ -367,7 +376,7 @@ public class KubesTest extends DefaultTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Collection<File> downloadTestXmlFromPod(String namespace, Pod cp) {
|
private Collection<File> downloadTestXmlFromPod(String namespace, Pod cp) {
|
||||||
String resultsInContainerPath = "/tmp/source/build/test-reports";
|
String resultsInContainerPath = TEST_RUN_DIR + "/test-reports";
|
||||||
String binaryResultsFile = "results.bin";
|
String binaryResultsFile = "results.bin";
|
||||||
String podName = cp.getMetadata().getName();
|
String podName = cp.getMetadata().getName();
|
||||||
Path tempDir = new File(new File(getProject().getBuildDir(), "test-results-xml"), podName).toPath();
|
Path tempDir = new File(new File(getProject().getBuildDir(), "test-results-xml"), podName).toPath();
|
||||||
@ -387,9 +396,10 @@ public class KubesTest extends DefaultTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String[] getBuildCommand(int numberOfPods, int podIdx) {
|
private String[] getBuildCommand(int numberOfPods, int podIdx) {
|
||||||
String shellScript = "let x=1 ; while [ ${x} -ne 0 ] ; do echo \"Waiting for DNS\" ; curl services.gradle.org > /dev/null 2>&1 ; x=$? ; sleep 1 ; done ; " + "cd /tmp/source ; " +
|
String shellScript = "(let x=1 ; while [ ${x} -ne 0 ] ; do echo \"Waiting for DNS\" ; curl services.gradle.org > /dev/null 2>&1 ; x=$? ; sleep 1 ; done ) && "
|
||||||
"let y=1 ; while [ ${y} -ne 0 ] ; do echo \"Preparing build directory\" ; ./gradlew testClasses integrationTestClasses --parallel 2>&1 ; y=$? ; sleep 1 ; done ;" +
|
+ " cd /tmp/source && " +
|
||||||
"./gradlew -D" + ListTests.DISTRIBUTION_PROPERTY + "=" + distribution.name() + " -Dkubenetize -PdockerFork=" + podIdx + " -PdockerForks=" + numberOfPods + " " + fullTaskToExecutePath + " " + getLoggingLevel() + " 2>&1 ;" +
|
"(let y=1 ; while [ ${y} -ne 0 ] ; do echo \"Preparing build directory\" ; ./gradlew testClasses integrationTestClasses --parallel 2>&1 ; y=$? ; sleep 1 ; done ) && " +
|
||||||
|
"(./gradlew -D" + ListTests.DISTRIBUTION_PROPERTY + "=" + distribution.name() + " -Dkubenetize -PdockerFork=" + podIdx + " -PdockerForks=" + numberOfPods + " " + fullTaskToExecutePath + " " + getLoggingLevel() + " 2>&1) ; " +
|
||||||
"let rs=$? ; sleep 10 ; exit ${rs}";
|
"let rs=$? ; sleep 10 ; exit ${rs}";
|
||||||
return new String[]{"bash", "-c", shellScript};
|
return new String[]{"bash", "-c", shellScript};
|
||||||
}
|
}
|
||||||
@ -421,13 +431,13 @@ public class KubesTest extends DefaultTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fileToInspect.isDirectory()) {
|
if (fileToInspect.isDirectory()) {
|
||||||
filesToInspect.addAll(Arrays.stream(fileToInspect.listFiles()).collect(Collectors.toList()));
|
filesToInspect.addAll(Arrays.stream(Optional.ofNullable(fileToInspect.listFiles()).orElse(new File[]{})).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExecListener buildExecListenerForPod(String podName, ByteArrayOutputStream errChannelStream, CompletableFuture<Integer> waitingFuture) {
|
private ExecListener buildExecListenerForPod(String podName, ByteArrayOutputStream errChannelStream, CompletableFuture<Integer> waitingFuture, KubernetesClient client) {
|
||||||
|
|
||||||
return new ExecListener() {
|
return new ExecListener() {
|
||||||
final Long start = System.currentTimeMillis();
|
final Long start = System.currentTimeMillis();
|
||||||
@ -457,6 +467,8 @@ public class KubesTest extends DefaultTask {
|
|||||||
waitingFuture.complete(resultCode);
|
waitingFuture.complete(resultCode);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
waitingFuture.completeExceptionally(e);
|
waitingFuture.completeExceptionally(e);
|
||||||
|
} finally {
|
||||||
|
client.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user