From bb388751c3c1b38923bfd070c6687dc4d33e1a22 Mon Sep 17 00:00:00 2001
From: "stu126940@mail.uni-kiel.de" <stu126940@mail.uni-kiel.de>
Date: Tue, 7 Dec 2021 23:06:28 +0100
Subject: [PATCH] Make it possible to set the timeout for an action in the
 benchmark manifests

---
 theodolite/crd/crd-benchmark.yaml                    | 12 ++++++++++++
 theodolite/examples/operator/example-benchmark.yaml  |  1 +
 .../src/main/kotlin/theodolite/benchmark/Action.kt   |  3 +++
 .../kotlin/theodolite/benchmark/ActionCommand.kt     | 12 ++++++++----
 .../src/main/kotlin/theodolite/util/Configuration.kt |  5 +++++
 5 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/theodolite/crd/crd-benchmark.yaml b/theodolite/crd/crd-benchmark.yaml
index 529d1ea42..394d6cc58 100644
--- a/theodolite/crd/crd-benchmark.yaml
+++ b/theodolite/crd/crd-benchmark.yaml
@@ -90,6 +90,8 @@ spec:
                               type: array
                               items:
                                 type: string
+                            timeout:
+                              type: integer
                   afterActions:
                     type: array
                     default: []
@@ -116,6 +118,8 @@ spec:
                               type: array
                               items:
                                 type: string
+                            timeout:
+                              type: integer
               sut:
                 description: The appResourceSets specifies all Kubernetes resources required to start the sut. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.
                 type: object
@@ -179,6 +183,8 @@ spec:
                               type: array
                               items:
                                 type: string
+                            timeout:
+                              type: integer
                   afterActions:
                     type: array
                     default: []
@@ -205,6 +211,8 @@ spec:
                               type: array
                               items:
                                 type: string
+                            timeout:
+                              type: integer
               loadGenerator:
                 description: The loadGenResourceSets specifies all Kubernetes resources required to start the load generator. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.
                 type: object
@@ -268,6 +276,8 @@ spec:
                               type: array
                               items:
                                 type: string
+                            timeout:
+                              type: integer
                   afterActions:
                     type: array
                     default: []
@@ -294,6 +304,8 @@ spec:
                               type: array
                               items:
                                 type: string
+                            timeout:
+                              type: integer
               resourceTypes:
                 description: A list of resource types that can be scaled for this `benchmark` resource. For each resource type the concrete values are defined in the `execution` object.
                 type: array
diff --git a/theodolite/examples/operator/example-benchmark.yaml b/theodolite/examples/operator/example-benchmark.yaml
index 945a05b38..b66852b1d 100644
--- a/theodolite/examples/operator/example-benchmark.yaml
+++ b/theodolite/examples/operator/example-benchmark.yaml
@@ -22,6 +22,7 @@ spec:
               app: busybox1
         exec:
           command: ["rm", "test-folder"]
+          timeout: 90
   loadGenerator:
     resources:
       - configMap:
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt
index 9fff88eea..edbffea36 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
 import theodolite.util.ActionCommandFailedException
+import theodolite.util.Configuration
 
 @JsonDeserialize
 @RegisterForReflection
@@ -19,6 +20,7 @@ class Action {
             .exec(
                 matchLabels = selector.pod.matchLabels,
                 container = selector.container,
+                timeout = exec.timeout,
                 command = exec.command
         )
             if(exitCode != 0){
@@ -42,4 +44,5 @@ class PodSelector {
 @RegisterForReflection
 class Command {
     lateinit var command: Array<String>
+    var timeout: Long = Configuration.TIMEOUT
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt
index bceb456c0..55c87074a 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt
@@ -6,6 +6,7 @@ import io.fabric8.kubernetes.client.dsl.ExecWatch
 import mu.KotlinLogging
 import okhttp3.Response
 import theodolite.util.ActionCommandFailedException
+import theodolite.util.Configuration
 import java.io.ByteArrayOutputStream
 import java.time.Duration
 import java.util.concurrent.CountDownLatch
@@ -13,7 +14,6 @@ import java.util.concurrent.TimeUnit
 import kotlin.properties.Delegates
 
 private val logger = KotlinLogging.logger {}
-private const val TIMEOUT = 30L
 
 class ActionCommand(val client: NamespacedKubernetesClient) {
     var out: ByteArrayOutputStream = ByteArrayOutputStream()
@@ -29,8 +29,12 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
      * @param command The command to be executed.
      * @return the exit code of this executed command
      */
-    fun exec(matchLabels: MutableMap<String, String>, command: Array<String>, container: String = ""): Int {
-
+    fun exec(
+        matchLabels: MutableMap<String, String>,
+        command: Array<String>,
+        timeout: Long = Configuration.TIMEOUT,
+        container: String = ""
+    ): Int {
         val exitCode = ExitCode()
 
         try {
@@ -50,7 +54,7 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
                 .usingListener(MyPodExecListener(execLatch, exitCode))
                 .exec(*command)
 
-            val latchTerminationStatus = execLatch.await(TIMEOUT, TimeUnit.SECONDS);
+            val latchTerminationStatus = execLatch.await(timeout, TimeUnit.SECONDS);
             if (!latchTerminationStatus) {
                 throw ActionCommandFailedException("Latch could not terminate within specified time")
             }
diff --git a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt b/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
index dac3b943e..97fffb8c9 100644
--- a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
@@ -13,6 +13,11 @@ class Configuration(
         val NAMESPACE = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
         val COMPONENT_NAME = System.getenv("COMPONENT_NAME") ?: DEFAULT_COMPONENT_NAME
         val EXECUTION_MODE = System.getenv("MODE") ?: ExecutionModes.STANDALONE.value
+
+        /**
+         * Specifies how long Theodolite should wait (in sec) before aborting the execution of an action command.
+         */
+        const val TIMEOUT: Long = 30L
     }
 
 }
-- 
GitLab