From adb14c0610415ba58a89552b3c588caa50739149 Mon Sep 17 00:00:00 2001
From: Gleb Kashkin <g.kashkin@tarantool.org>
Date: Fri, 12 May 2023 17:05:27 +0000
Subject: [PATCH] box: add hostname to box.info

Hostname is a useful piece of information in state reports. So it was
decided to add it to box.info.

Hostname is obtained on requested and is not cached.

Closes #8605

@TarantoolBot document
Title: Add hostname to box.info

This patch adds hostname to box.info, it can be useful e.g. to supplement
various instance state reports. It is not cached and is requested on
each call.
---
 .../unreleased/gh-8605-add-gethostname.md     |  3 ++
 src/box/lua/info.c                            | 30 +++++++++++++++++++
 .../gh_8605_add_box_info_hostname_test.lua    | 21 +++++++++++++
 test/box/info.result                          |  5 ++++
 test/box/info.test.lua                        |  1 +
 5 files changed, 60 insertions(+)
 create mode 100644 changelogs/unreleased/gh-8605-add-gethostname.md
 create mode 100644 test/box-luatest/gh_8605_add_box_info_hostname_test.lua

diff --git a/changelogs/unreleased/gh-8605-add-gethostname.md b/changelogs/unreleased/gh-8605-add-gethostname.md
new file mode 100644
index 0000000000..af92672f37
--- /dev/null
+++ b/changelogs/unreleased/gh-8605-add-gethostname.md
@@ -0,0 +1,3 @@
+## feature/box
+
+* Added a new `box.info` parameter `hostname` (gh-8605).
diff --git a/src/box/lua/info.c b/src/box/lua/info.c
index 8664965c91..05bf09389f 100644
--- a/src/box/lua/info.c
+++ b/src/box/lua/info.c
@@ -31,6 +31,7 @@
 #include "lua/info.h"
 
 #include <ctype.h> /* tolower() */
+#include <unistd.h>
 
 #include <lua.h>
 #include <lauxlib.h>
@@ -69,6 +70,18 @@
 static bool box_info_cluster_new_meaning = true;
 TWEAK_BOOL(box_info_cluster_new_meaning);
 
+/**
+ * Known upper limits for a hostname (without a zero-terminating
+ * byte):
+ *
+ * sysconf(_SC_HOST_NAME_MAX) == 64 on Linux.
+ * sysconf(_SC_HOST_NAME_MAX) == 255 on macOS.
+ * sysconf(_SC_HOST_NAME_MAX) == 255 on BSD.
+ *
+ * The constant value is used to simplify the code.
+ */
+enum { TT_HOST_NAME_MAX = 255 };
+
 static inline void
 lbox_push_replication_error_message(struct lua_State *L, struct error *e,
 				    int idx)
@@ -701,6 +714,22 @@ lbox_schema_version(struct lua_State *L)
 	return 1;
 }
 
+/** gethostname() Lua interface inside box.info. */
+static int
+lbox_info_hostname(struct lua_State *L)
+{
+	char buffer[TT_HOST_NAME_MAX + 1];
+	int rc = gethostname(buffer, sizeof(buffer));
+	if (rc != 0) {
+		say_warn_ratelimited("failed to get hostname: %s",
+				     tt_strerror(errno));
+		lua_pushnil(L);
+		return 1;
+	}
+	lua_pushstring(L, buffer);
+	return 1;
+}
+
 static const struct luaL_Reg lbox_info_dynamic_meta[] = {
 	{"id", lbox_info_id},
 	{"uuid", lbox_info_uuid},
@@ -725,6 +754,7 @@ static const struct luaL_Reg lbox_info_dynamic_meta[] = {
 	{"election", lbox_info_election},
 	{"synchro", lbox_info_synchro},
 	{"schema_version", lbox_schema_version},
+	{"hostname", lbox_info_hostname},
 	{NULL, NULL}
 };
 
diff --git a/test/box-luatest/gh_8605_add_box_info_hostname_test.lua b/test/box-luatest/gh_8605_add_box_info_hostname_test.lua
new file mode 100644
index 0000000000..5bad6a32f4
--- /dev/null
+++ b/test/box-luatest/gh_8605_add_box_info_hostname_test.lua
@@ -0,0 +1,21 @@
+local popen = require('popen')
+local t = require('luatest')
+
+local g = t.group()
+
+g.test_hostname_result = function()
+    local ph = popen.shell("hostname", 'r')
+
+    local exp_status = {
+        state = popen.state.EXITED,
+        exit_code = 0,
+    }
+    local status = ph:wait()
+    t.skip_if(status.exit_code == 127, "no hostname on host")
+    t.assert_equals(status, exp_status, 'verify process status')
+
+    local hostname = ph:read():rstrip()
+    t.assert_equals(hostname, box.info.hostname, 'verify hostname')
+
+    ph:close()
+end
diff --git a/test/box/info.result b/test/box/info.result
index 6db9b6d5af..19bb50a328 100644
--- a/test/box/info.result
+++ b/test/box/info.result
@@ -63,6 +63,10 @@ box.info.replicaset.uuid == box.space._schema:get{'replicaset_uuid'}[2]
 ---
 - true
 ...
+type(box.info.hostname) == 'string'
+---
+- true
+...
 t = {}
 ---
 ...
@@ -77,6 +81,7 @@ t
 - - cluster
   - election
   - gc
+  - hostname
   - id
   - listen
   - lsn
diff --git a/test/box/info.test.lua b/test/box/info.test.lua
index 19056301bd..51a9c509df 100644
--- a/test/box/info.test.lua
+++ b/test/box/info.test.lua
@@ -17,6 +17,7 @@ box.info.status
 string.len(box.info.uptime) > 0
 string.match(box.info.uptime, '^[1-9][0-9]*$') ~= nil
 box.info.replicaset.uuid == box.space._schema:get{'replicaset_uuid'}[2]
+type(box.info.hostname) == 'string'
 t = {}
 for k, _ in pairs(box.info()) do table.insert(t, k) end
 table.sort(t)
-- 
GitLab