From cb553aef625cb6621760efc6ae83f84e445c00b0 Mon Sep 17 00:00:00 2001 From: "stu126940@mail.uni-kiel.de" <stu126940@mail.uni-kiel.de> Date: Wed, 2 Jun 2021 21:34:12 +0200 Subject: [PATCH] add leader election in operator mode --- .../execution/operator/LeaderElector.kt | 43 +++++++++++++++++++ .../execution/operator/TheodoliteOperator.kt | 13 +++++- 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt new file mode 100644 index 000000000..9d093e485 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt @@ -0,0 +1,43 @@ +package theodolite.execution.operator + +import io.fabric8.kubernetes.client.DefaultKubernetesClient +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import io.fabric8.kubernetes.client.extended.leaderelection.LeaderCallbacks +import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElectionConfigBuilder +import io.fabric8.kubernetes.client.extended.leaderelection.resourcelock.LeaseLock +import mu.KotlinLogging +import java.time.Duration +import java.util.* +import kotlin.reflect.KFunction0 + +private val logger = KotlinLogging.logger {} + +class LeaderElector( + val client: NamespacedKubernetesClient, + val name: String + ) { + + fun getLeadership(leader: KFunction0<Unit>) { + val lockIdentity: String = UUID.randomUUID().toString() + DefaultKubernetesClient().use { kc -> + kc.leaderElector() + .withConfig( + LeaderElectionConfigBuilder() + .withName("Theodolite") + .withLeaseDuration(Duration.ofSeconds(15L)) + .withLock(LeaseLock(client.namespace, name, lockIdentity)) + .withRenewDeadline(Duration.ofSeconds(10L)) + .withRetryPeriod(Duration.ofSeconds(2L)) + .withLeaderCallbacks(LeaderCallbacks( + { Thread{leader()}.start() }, + { logger.info { "STOPPED LEADERSHIP" } } + ) { newLeader: String? -> + logger.info { "New leader elected $newLeader" } + }) + .build() + ) + .build().run() + } + } + +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt index 5e15a4a80..0acfc5288 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt @@ -28,13 +28,22 @@ private val logger = KotlinLogging.logger {} */ class TheodoliteOperator { private val namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE + val client = DefaultKubernetesClient().inNamespace(namespace) + + + fun start() { + LeaderElector( + client = client, + name = "theodolite-operator" + ) + .getLeadership(::startOperator) + } /** * Start the operator. */ - fun start() { + private fun startOperator() { logger.info { "Using $namespace as namespace." } - val client = DefaultKubernetesClient().inNamespace(namespace) KubernetesDeserializer.registerCustomKind( "$GROUP/$API_VERSION", -- GitLab