From 1cec5bd4e40267b7399100417d218f3f7fc2bba2 Mon Sep 17 00:00:00 2001
From: Egor Ivkov <e.ivkov@picodata.io>
Date: Fri, 20 Jan 2023 12:00:42 +0000
Subject: [PATCH] feature: postjoin script

---
 src/args.rs             |  9 +++++++++
 src/main.rs             |  7 +++++++
 test/int/test_script.py | 21 +++++++++++++++++++++
 3 files changed, 37 insertions(+)
 create mode 100644 test/int/test_script.py

diff --git a/src/args.rs b/src/args.rs
index 3b65305443..69add9b906 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -116,6 +116,15 @@ pub struct Run {
     /// the cluster. It's only accounted upon the cluster initialization
     /// (when the first instance bootstraps), and ignored aftwerwards.
     pub init_replication_factor: u8,
+
+    #[clap(
+        long,
+        value_name = "path",
+        env = "PICODATA_SCRIPT",
+        parse(try_from_str = try_parse_path)
+    )]
+    /// A path to a lua script that will be executed at postjoin stage
+    pub script: Option<String>,
 }
 
 // Copy enum because clap:ArgEnum can't be derived for the foreign SayLevel.
diff --git a/src/main.rs b/src/main.rs
index ddad33dafe..689101f7f7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -992,6 +992,13 @@ fn start_join(args: &args::Run, leader_address: String) {
 fn postjoin(args: &args::Run, storage: Clusterwide, raft_storage: RaftSpaceAccess) {
     tlog!(Info, ">>>>> postjoin()");
 
+    // Execute postjoin script if present
+    if let Some(ref script) = args.script {
+        let l = ::tarantool::lua_state();
+        l.exec(&format!("dofile('{script}')"))
+            .unwrap_or_else(|err| panic!("failed to execute postjoin script: {err}"))
+    }
+
     let mut box_cfg = tarantool::cfg().unwrap();
 
     // Reset the quorum BEFORE initializing the raft node.
diff --git a/test/int/test_script.py b/test/int/test_script.py
new file mode 100644
index 0000000000..c5c721119d
--- /dev/null
+++ b/test/int/test_script.py
@@ -0,0 +1,21 @@
+from conftest import Cluster
+
+
+def test_script_failure(cluster: Cluster):
+    instance = cluster.add_instance(wait_online=False)
+    script = f"{cluster.data_dir}/fail.lua"
+    with open(script, "w") as f:
+        f.write("assert(false)")
+    instance.env["PICODATA_SCRIPT"] = script
+    instance.fail_to_start()
+    instance.terminate()
+
+
+def test_script(cluster: Cluster):
+    instance = cluster.add_instance(wait_online=False)
+    script = f"{cluster.data_dir}/ok.lua"
+    with open(script, "w") as f:
+        f.write("assert(type(box.cfg) == 'table')")
+    instance.env["PICODATA_SCRIPT"] = script
+    instance.start()
+    instance.wait_online()
-- 
GitLab