Repository: irods/irods
Pull request #8338: [#8287] Use `host` property instead of `gethostname` and `boost::asio::host_name` (main)
Author: login: korydraughn
Created: 2025-03-27T21:19:15Z | Merged: 2025-03-31T14:22:26Z

Need to run all the tests.

Also need to address TODO comments.


Diff:
diff --git a/lib/core/src/sockComm.cpp b/lib/core/src/sockComm.cpp
index e161e42eb3..49ee202de5 100644
--- a/lib/core/src/sockComm.cpp
+++ b/lib/core/src/sockComm.cpp
@@ -479,7 +479,8 @@ sockOpenForInConn( rsComm_t *rsComm, int *portNum, char **addr, int proto ) {
             constexpr auto size_in_bytes = sizeof(char) * LONG_NAME_LEN;
             *addr = static_cast<char*>(std::malloc(size_in_bytes));
             std::memset(*addr, 0, size_in_bytes);
-            gethostname(*addr, LONG_NAME_LEN);
+            const auto hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
+            hostname.copy(*addr, size_in_bytes - 1);
 
             try {
                 const auto alias = resolve_hostname(*addr, hostname_resolution_scheme::match_longest);
diff --git a/plugins/microservices/src/get_hostname.cpp b/plugins/microservices/src/get_hostname.cpp
index 42bb072a26..588260fc4f 100644
--- a/plugins/microservices/src/get_hostname.cpp
+++ b/plugins/microservices/src/get_hostname.cpp
@@ -14,24 +14,24 @@
 
 namespace
 {
-    int msi_impl(msParam_t *_out, ruleExecInfo_t* _rei){
+    int msi_impl(msParam_t* _out, ruleExecInfo_t* _rei)
+    {
         if (!_out || !_rei){
             return SYS_INTERNAL_NULL_INPUT_ERR;
         }
-        char hostname[HOST_NAME_MAX + 1]{};
-        gethostname(hostname, sizeof(hostname));
         fillStrInMsParam(_out, _rei->rsComm->myEnv.rodsHost);
         return 0;
-    }// msi_impl
+    } // msi_impl
 
     template <typename... Args, typename Function>
     auto make_msi(const std::string& name, Function func) -> irods::ms_table_entry*
     {
+        // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
         auto* msi = new irods::ms_table_entry{sizeof...(Args)};
         msi->add_operation(name, std::function<int(Args..., ruleExecInfo_t*)>(func));
         return msi;
     } // make_msi
-}// anonymous namespace
+} // anonymous namespace
 
 extern "C"
 auto plugin_factory() -> irods::ms_table_entry* {
diff --git a/plugins/resources/replication/src/librepl.cpp b/plugins/resources/replication/src/librepl.cpp
index 3426ac29bd..7c3e4c20d6 100644
--- a/plugins/resources/replication/src/librepl.cpp
+++ b/plugins/resources/replication/src/librepl.cpp
@@ -6,6 +6,8 @@
 // =-=-=-=-=-=-=-
 // irods includes
 #include "irods/icatHighLevelRoutines.hpp"
+#include "irods/irods_configuration_keywords.hpp"
+#include "irods/irods_server_properties.hpp"
 #include "irods/msParam.h"
 #include "irods/rodsLog.h"
 
@@ -432,11 +434,7 @@ irods::error create_replication_list(
     }
 
     // Get current hostname for vote
-    char host_name_str[MAX_NAME_LEN];
-    if (gethostname(host_name_str, MAX_NAME_LEN) < 0) {
-        return ERROR(SYS_GET_HOSTNAME_ERR, "failed in gethostname");
-    }
-    const std::string host_name(host_name_str);
+    const auto host_name = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
 
     // Loop over children and create a list of hierarchies to which objects will be replicated
     float out_vote{};
diff --git a/plugins/resources/unixfilesystem/src/unixfilesystem.cpp b/plugins/resources/unixfilesystem/src/unixfilesystem.cpp
index f2bd46b41b..59ccd45559 100644
--- a/plugins/resources/unixfilesystem/src/unixfilesystem.cpp
+++ b/plugins/resources/unixfilesystem/src/unixfilesystem.cpp
@@ -1,5 +1,6 @@
 // =-=-=-=-=-=-=-
 // irods includes
+#include "irods/irods_configuration_keywords.hpp"
 #include "irods/msParam.h"
 #include "irods/rcConnect.h"
 #include "irods/miscServerFunct.hpp"
@@ -117,13 +118,11 @@ auto unix_file_start_operation(irods::plugin_property_map& prop_map) -> irods::e
     }
 
     // check if we are in the host list
-    char local_hostname[MAX_NAME_LEN];
-    gethostname(local_hostname, MAX_NAME_LEN);
-
+    const auto local_hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
     auto resource_hostname_optional = resolve_hostname(local_hostname, hostname_resolution_scheme::match_preferred);
 
     std::string resource_hostname =
-        resource_hostname_optional ? std::move(*resource_hostname_optional) : local_hostname;
+        resource_hostname_optional ? *std::move(resource_hostname_optional) : local_hostname;
 
     if (!is_host_in_host_list(prop_map, resource_hostname)) {
         // Host is not in host list.  Return early as detached mode is disabled on this resource.
@@ -153,7 +152,7 @@ auto unix_file_start_operation(irods::plugin_property_map& prop_map) -> irods::e
     // Note that the rodsHostAddr_t entry is shared throughout the code (not just used for this
     // resource) so you can't adjust the existing entry attached to the resource.
     rodsHostAddr_t addr{};
-    std::strncpy(addr.hostAddr, local_hostname, LONG_NAME_LEN);
+    std::strncpy(addr.hostAddr, local_hostname.c_str(), LONG_NAME_LEN);
     const auto& zone_name = irods::get_server_property<const std::string>(irods::KW_CFG_ZONE_NAME);
     std::strncpy(addr.zoneName, zone_name.c_str(), NAME_LEN);
 
diff --git a/plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp b/plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp
index de8bce24a4..9b1ae2b6cf 100644
--- a/plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp
+++ b/plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp
@@ -1,6 +1,3 @@
-/*** Copyright (c), The Regents of the University of California            ***
- *** For more information please refer to files in the COPYRIGHT directory ***/
-
 #include "irods/private/re/reHelpers1.hpp"
 
 #include "irods/private/re/reFuncDefs.hpp"
@@ -9,9 +6,10 @@
 #include "irods/private/re/filesystem.hpp"
 #include "irods/private/re/configuration.hpp"
 
-#include "irods/rcMisc.h"
+#include "irods/irods_configuration_keywords.hpp"
 #include "irods/irods_log.hpp"
-
+#include "irods/irods_server_properties.hpp"
+#include "irods/rcMisc.h"
 
 struct Breakpoint {
     char *actionName;
@@ -50,16 +48,17 @@ int myPID;
 int initializeReDebug( rsComm_t *svrComm ) {
     char condRead[NAME_LEN];
 
-    if ( svrComm == NULL ) {
+    if (svrComm == nullptr) {
         return 0;
     }
     if ( GlobalREDebugFlag != 4 ) {
         return 0;
     }
 
-    myPID = ( int ) getpid();
-    myHostName[0] = '\0';
-    gethostname( myHostName, MAX_NAME_LEN );
+    myPID = getpid();
+    std::memset(myHostName, 0, sizeof(myHostName));
+    const auto hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
+    hostname.copy(myHostName, sizeof(myHostName) - 1);
     sprintf( condRead, "(*XUSER  == \"%s@%s\") && (*XHDR == \"STARTDEBUG\")",
              svrComm->clientUser.userName, svrComm->clientUser.rodsZone );
     return 0;
diff --git a/schemas/configuration/v5/server_config.json.in b/schemas/configuration/v5/server_config.json.in
index cde22249ae..d2adda4b74 100644
--- a/schemas/configuration/v5/server_config.json.in
+++ b/schemas/configuration/v5/server_config.json.in
@@ -103,7 +103,11 @@
             "type": "integer",
             "minimum": 0
         },
-        "host": {"type": "string"},
+        "host": {
+            "type": "string",
+            "minLength": 1,
+            "maxLength": 253
+        },
         "host_access_control": {
             "$ref": "host_access_control.json"
         },
diff --git a/scripts/irods/test/test_misc.py b/scripts/irods/test/test_misc.py
index 7de204e642..59ccfc556e 100644
--- a/scripts/irods/test/test_misc.py
+++ b/scripts/irods/test/test_misc.py
@@ -1,8 +1,10 @@
 import os
+import subprocess
 import sys
-from datetime import datetime, timedelta
 import tempfile
 
+from datetime import datetime, timedelta
+
 if sys.version_info < (2, 7):
     import unittest2 as unittest
 else:
@@ -477,3 +479,36 @@ def test_logical_path_including_the_AND_keyword_SPACES_and_a_SINGLE_QUOTATION_MA
         finally:
             if os.path.exists(filename):
                 os.unlink(filename)
+
+    @unittest.skipIf(test.settings.RUN_IN_TOPOLOGY, 'Only requires a single server')
+    def test_configuration_validation_reports_fqdn_size_violations__issue_8287(self):
+        # See https://web.archive.org/web/20190518124533/https://devblogs.microsoft.com/oldnewthing/?p=7873
+        # to understand why the "host" property limits the length to 253 characters.
+
+        config = IrodsConfig()
+
+        with lib.file_backed_up(config.server_config_path):
+            with self.subTest('"host" property is an empty string'):
+                config.server_config['host'] = ''
+                lib.update_json_file_from_dict(config.server_config_path, config.server_config)
+                res = subprocess.run(['irodsServer', '-c'], capture_output=True, text=True)
+                self.assertNotEqual(res.returncode, 0)
+                self.assertIn('"valid": false', res.stderr)
+                self.assertIn('"instanceLocation": "/host"', res.stderr)
+                self.assertIn('"error": "Number of characters must be at least 1"', res.stderr)
+
+            with self.subTest('"host" property has size matching limit (253 characters)'):
+                config.server_config['host'] = 'a' * 253
+                lib.update_json_file_from_dict(config.server_config_path, config.server_config)
+                res = subprocess.run(['irodsServer', '-c'], capture_output=True, text=True)
+                self.assertEqual(res.returncode, 0)
+                self.assertEqual(len(res.stderr), 0)
+
+            with self.subTest('"host" property has size exceeding limit (253 characters)'):
+                config.server_config['host'] = 'a' * 254
+                lib.update_json_file_from_dict(config.server_config_path, config.server_config)
+                res = subprocess.run(['irodsServer', '-c'], capture_output=True, text=True)
+                self.assertNotEqual(res.returncode, 0)
+                self.assertIn('"valid": false', res.stderr)
+                self.assertIn('"instanceLocation": "/host"', res.stderr)
+                self.assertIn('"error": "Number of characters must be at most 253"', res.stderr)
diff --git a/scripts/setup_irods.py b/scripts/setup_irods.py
index 33bcf1f256..936b4b9222 100755
--- a/scripts/setup_irods.py
+++ b/scripts/setup_irods.py
@@ -204,9 +204,9 @@ def setup_server_host(irods_config):
     l = logging.getLogger(__name__)
 
     irods_config.server_config['host'] = irods.lib.default_prompt(
-        'iRODS server FQDN, hostname, or IP (256 characters max)',
+        'iRODS server FQDN, hostname, or IP (253 characters max)',
         default=[irods.lib.get_hostname()],
-        input_filter=irods.lib.character_count_filter(minimum=1, maximum=256, field='iRODS server host'))
+        input_filter=irods.lib.character_count_filter(minimum=1, maximum=253, field='iRODS server host'))
 
     irods_config.commit(irods_config.server_config, irods_config.server_config_path, clear_cache=False)
 
diff --git a/server/api/src/rsGeneralAdmin.cpp b/server/api/src/rsGeneralAdmin.cpp
index 378a4b0ffa..2e18ae755e 100644
--- a/server/api/src/rsGeneralAdmin.cpp
+++ b/server/api/src/rsGeneralAdmin.cpp
@@ -2,26 +2,28 @@
 
 #include "irods/administration_utilities.hpp"
 #include "irods/generalAdmin.h"
-#include "irods/rcMisc.h"
-#include "irods/rsZoneReport.hpp"
-#include "irods/rodsConnect.h"
 #include "irods/icatHighLevelRoutines.hpp"
-#include "irods/miscServerFunct.hpp"
-#include "irods/rodsErrorTable.h"
-#include "irods/rsModAVUMetadata.hpp"
-#include "irods/rsGenQuery.hpp"
+#include "irods/irods_at_scope_exit.hpp"
 #include "irods/irods_children_parser.hpp"
-#include "irods/irods_string_tokenize.hpp"
-#include "irods/irods_plugin_name_generator.hpp"
-#include "irods/irods_resource_manager.hpp"
+#include "irods/irods_configuration_keywords.hpp"
 #include "irods/irods_file_object.hpp"
-#include "irods/irods_resource_constants.hpp"
-#include "irods/irods_load_plugin.hpp"
-#include "irods/irods_at_scope_exit.hpp"
 #include "irods/irods_hierarchy_parser.hpp"
+#include "irods/irods_load_plugin.hpp"
 #include "irods/irods_logger.hpp"
-#include "irods/user_validation_utilities.hpp"
+#include "irods/irods_plugin_name_generator.hpp"
+#include "irods/irods_resource_constants.hpp"
+#include "irods/irods_resource_manager.hpp"
+#include "irods/irods_server_properties.hpp"
+#include "irods/irods_string_tokenize.hpp"
+#include "irods/miscServerFunct.hpp"
+#include "irods/rcMisc.h"
+#include "irods/rodsConnect.h"
+#include "irods/rodsErrorTable.h"
+#include "irods/rsGenQuery.hpp"
+#include "irods/rsModAVUMetadata.hpp"
+#include "irods/rsZoneReport.hpp"
 #include "irods/rs_set_delay_server_migration_info.hpp"
+#include "irods/user_validation_utilities.hpp"
 #include "irods/version.hpp"
 
 #define IRODS_USER_ADMINISTRATION_ENABLE_SERVER_SIDE_API
@@ -181,8 +183,7 @@ namespace
 
     auto get_value_for_rebalance_avu() -> std::string
     {
-        char hostname[MAX_NAME_LEN];
-        gethostname(hostname, MAX_NAME_LEN);
+        const auto hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
         return fmt::format("{}:{}", hostname, getpid());
     } // get_value_for_rebalance_avu
 
diff --git a/server/api/src/rsServerReport.cpp b/server/api/src/rsServerReport.cpp
index 06462194d2..6a5b491e16 100644
--- a/server/api/src/rsServerReport.cpp
+++ b/server/api/src/rsServerReport.cpp
@@ -1,5 +1,6 @@
 #include "irods/rsServerReport.hpp"
 
+#include "irods/irods_configuration_keywords.hpp"
 #include "irods/irods_default_paths.hpp"
 #include "irods/irods_environment_properties.hpp"
 #include "irods/irods_get_full_path_for_config_file.hpp"
@@ -236,14 +237,7 @@ irods::error get_host_system_information(json& _host_system_information)
         _host_system_information["service_account_group_name"] = nullptr;
     }
 
-    char hostname_buf[512];
-    const int gethostname_ret = gethostname(hostname_buf, sizeof(hostname_buf));
-    if (gethostname_ret != 0) {
-        rodsLog(LOG_ERROR, "get_host_system_information: gethostname() failed [%d]", errno);
-        _host_system_information["hostname"] = nullptr;
-    } else {
-        _host_system_information["hostname"] = hostname_buf;
-    }
+    _host_system_information["hostname"] = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
 
     std::string uname_string;
     ret = get_uname_string( uname_string );
diff --git a/server/core/include/irods/rodsConnect.h b/server/core/include/irods/rodsConnect.h
index a2b93268e0..ddb0a1d921 100644
--- a/server/core/include/irods/rodsConnect.h
+++ b/server/core/include/irods/rodsConnect.h
@@ -70,7 +70,7 @@ typedef struct zoneInfo {
 extern "C" {
 #endif
 
-int queueAddr(rodsServerHost_t *rodsServerHost, char *myHostName);
+int queueAddr(rodsServerHost_t* rodsServerHost, const char* myHostName);
 
 int queueHostName(rodsServerHost_t *rodsServerHost,
                   const char *myHostName,
diff --git a/server/core/src/initServer.cpp b/server/core/src/initServer.cpp
index 030366dea7..abb2535ae0 100644
--- a/server/core/src/initServer.cpp
+++ b/server/core/src/initServer.cpp
@@ -222,21 +222,13 @@ initLocalServerHost() {
     }
 
     queueHostName( ServerHostHead, "localhost", 0 );
-    char myHostName[MAX_NAME_LEN];
-    status = gethostname( myHostName, MAX_NAME_LEN );
-    if ( status < 0 ) {
-        status = SYS_GET_HOSTNAME_ERR - errno;
-        rodsLog( LOG_NOTICE,
-                 "initLocalServerHost: gethostname error, status = %d",
-                 status );
-        return status;
-    }
-    status = queueHostName( ServerHostHead, myHostName, 0 );
+    const auto myHostName = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
+    status = queueHostName(ServerHostHead, myHostName.c_str(), 0);
     if ( status < 0 ) {
         return status;
     }
 
-    status = queueAddr( ServerHostHead, myHostName );
+    status = queueAddr(ServerHostHead, myHostName.c_str());
     if ( status < 0 ) {
         /* some configuration may not be able to resolve myHostName. So don't
          * exit. Just print out warning */
diff --git a/server/core/src/irods_resource_redirect.cpp b/server/core/src/irods_resource_redirect.cpp
index 6012419212..433e4e84f9 100644
--- a/server/core/src/irods_resource_redirect.cpp
+++ b/server/core/src/irods_resource_redirect.cpp
@@ -1,3 +1,5 @@
+#include "irods/irods_configuration_keywords.hpp"
+#include "irods/irods_server_properties.hpp"
 #include "irods/miscServerFunct.hpp"
 #include "irods/objInfo.h"
 #include "irods/dataObjCreate.h"
@@ -131,17 +133,11 @@ namespace
                        "attempt to directly address a child resource" );
         }
 
-        // get current hostname, which is also done by init local server host
-        char host_name_str[MAX_NAME_LEN]{};
-        if ( gethostname( host_name_str, MAX_NAME_LEN ) < 0 ) {
-            return ERROR( SYS_GET_HOSTNAME_ERR, "failed in gethostname" );
-        }
-
         // query the resc given the operation for a hier string which
         // will determine the host
         irods::hierarchy_parser parser;
         float vote{};
-        std::string host_name{host_name_str};
+        std::string host_name = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
         irods::first_class_object_ptr ptr = boost::dynamic_pointer_cast<irods::first_class_object>(_file_obj);
         err = resc->call< const std::string*, const std::string*, irods::hierarchy_parser*, float* >(
                   _comm, irods::RESOURCE_OP_RESOLVE_RESC_HIER, ptr, &_oper, &host_name, &parser, &vote );
@@ -490,14 +486,7 @@ namespace irods
             return PASSMSG( msg.str(), err );
         }
 
-        // =-=-=-=-=-=-=-
-        // get current hostname, which is also done by init local server host
-        char host_name_char[ MAX_NAME_LEN ];
-        if ( gethostname( host_name_char, MAX_NAME_LEN ) < 0 ) {
-            return ERROR( SYS_GET_HOSTNAME_ERR, "failed in gethostname" );
-        }
-
-        std::string host_name( host_name_char );
+        const auto host_name = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
 
         // =-=-=-=-=-=-=
         // iterate over the list of hostName_t* and see if any match our
diff --git a/server/core/src/rodsConnect.cpp b/server/core/src/rodsConnect.cpp
index 018923c323..345a5eb6d6 100644
--- a/server/core/src/rodsConnect.cpp
+++ b/server/core/src/rodsConnect.cpp
@@ -146,8 +146,8 @@ mkServerHost(char *myHostAddr, char *zoneName) {
     return tmpRodsServerHost;
 }
 
-int
-queueAddr( rodsServerHost_t *rodsServerHost, char *myHostName ) {
+int queueAddr(rodsServerHost_t* rodsServerHost, const char* myHostName)
+{
     if ( rodsServerHost == NULL || myHostName == NULL ) {
         return 0;
     }
diff --git a/server/delay_server/src/irodsDelayServer.cpp b/server/delay_server/src/irodsDelayServer.cpp
index 80b712fabf..eb80ed2c23 100644
--- a/server/delay_server/src/irodsDelayServer.cpp
+++ b/server/delay_server/src/irodsDelayServer.cpp
@@ -762,19 +762,13 @@ namespace
     auto is_local_server_defined_as_delay_server_leader() -> bool
     {
         std::string hostname;
-        //NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
-        char hn[HOST_NAME_MAX + 1]{};
-
-        if (const auto err = gethostname(hn, sizeof(hn)); err != 0) {
-            log_ds::error("{}: Failed to retrieve local server's hostname. Error {}", __func__, err);
-            return false;
-        }
+        auto hn = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
 
         if (const auto hn_resolved = resolve_hostname(hn, hostname_resolution_scheme::match_preferred); hn_resolved) {
             hostname = *hn_resolved;
         }
         else {
-            hostname = hn;
+            hostname = std::move(hn);
         }
         irods::experimental::client_connection conn;
         GridConfigurationInput input{};
@@ -782,7 +776,7 @@ namespace
         std::strcpy(input.option_name, "leader");
 
         GridConfigurationOutput* output{};
-        //NOLINTNEXTLINE(cppcoreguidelines-no-malloc, cppcoreguidelines-owning-memory)
+        // NOLINTNEXTLINE(cppcoreguidelines-no-malloc, cppcoreguidelines-owning-memory)
         irods::at_scope_exit free_output{[&output] { std::free(output); }};
 
         if (const auto ec = rc_get_grid_configuration_value(static_cast<RcComm*>(conn), &input, &output); ec != 0) {
@@ -797,7 +791,7 @@ namespace
             return hostname == *hn_resolved;
         }
         return hostname == output->option_value;
-    } //is_local_server_defined_as_delay_server_leader
+    } // is_local_server_defined_as_delay_server_leader
 
 } // anonymous namespace
 


Reviews:
user: login: alanking
body: Will review again upon addressing of TODO(s). Looks like some clang-format will be in order as well.

If the sorting of the header includes will be left as a separate commit, please put a filename or some other identifier in the commit message, e.g. "rsGeneralAdmin: Sort header includes"
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T21:52:40Z
user: login: trel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-28T02:02:12Z
user: login: alanking
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T13:19:41Z
user: login: korydraughn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T14:06:10Z
user: login: trel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-28T14:22:18Z
user: login: alanking
body: Will approve once we have the test results and an issue number on that last commit.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T19:38:46Z
user: login: korydraughn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-29T17:50:44Z
user: login: korydraughn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-29T17:52:05Z
user: login: trel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-29T17:53:03Z
user: login: korydraughn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-29T20:10:33Z
user: login: trel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-29T20:11:48Z
user: login: korydraughn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-29T20:11:51Z
user: login: trel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-29T20:14:35Z
user: login: trel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-29T20:14:53Z
user: login: trel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-29T20:15:50Z
user: login: korydraughn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-29T20:28:35Z
user: login: korydraughn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-29T20:28:43Z
user: login: trel
body: if things are passing - seems ready for squashing
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-29T20:46:55Z
user: login: alanking
body: Seems good. \# it
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T13:10:53Z

Review comments:
diff_hunk: @@ -50,16 +48,17 @@ int myPID;
 int initializeReDebug( rsComm_t *svrComm ) {
     char condRead[NAME_LEN];
 
-    if ( svrComm == NULL ) {
+    if (svrComm == nullptr) {
         return 0;
     }
     if ( GlobalREDebugFlag != 4 ) {
         return 0;
     }
 
-    myPID = ( int ) getpid();
-    myHostName[0] = '\0';
-    gethostname( myHostName, MAX_NAME_LEN );
+    myPID = getpid();
+    std::memset(myHostName, 0, sizeof(myHostName));
+    const auto hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
+    hostname.copy(myHostName, sizeof(myHostName) - 1);
path: plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp
user: login: trel
body: why have both `myHostName` and `hostname` here... maybe i'm just not seeing it...?
created_at: 2025-03-28T02:02:12Z
author_association: MEMBER
diff_hunk: @@ -50,16 +48,17 @@ int myPID;
 int initializeReDebug( rsComm_t *svrComm ) {
     char condRead[NAME_LEN];
 
-    if ( svrComm == NULL ) {
+    if (svrComm == nullptr) {
         return 0;
     }
     if ( GlobalREDebugFlag != 4 ) {
         return 0;
     }
 
-    myPID = ( int ) getpid();
-    myHostName[0] = '\0';
-    gethostname( myHostName, MAX_NAME_LEN );
+    myPID = getpid();
+    std::memset(myHostName, 0, sizeof(myHostName));
+    const auto hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
+    hostname.copy(myHostName, sizeof(myHostName) - 1);
path: plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp
user: login: alanking
body: `get_server_property` is returning a `std::string`, and `myHostName` seems to be a global/static `char[]` into which that string needs to be copied. `myHostName` is used elsewhere, presumably/hopefully.
created_at: 2025-03-28T13:19:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -50,16 +48,17 @@ int myPID;
 int initializeReDebug( rsComm_t *svrComm ) {
     char condRead[NAME_LEN];
 
-    if ( svrComm == NULL ) {
+    if (svrComm == nullptr) {
         return 0;
     }
     if ( GlobalREDebugFlag != 4 ) {
         return 0;
     }
 
-    myPID = ( int ) getpid();
-    myHostName[0] = '\0';
-    gethostname( myHostName, MAX_NAME_LEN );
+    myPID = getpid();
+    std::memset(myHostName, 0, sizeof(myHostName));
+    const auto hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
+    hostname.copy(myHostName, sizeof(myHostName) - 1);
path: plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp
user: login: korydraughn
body: Correct.
created_at: 2025-03-28T14:06:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -50,16 +48,17 @@ int myPID;
 int initializeReDebug( rsComm_t *svrComm ) {
     char condRead[NAME_LEN];
 
-    if ( svrComm == NULL ) {
+    if (svrComm == nullptr) {
         return 0;
     }
     if ( GlobalREDebugFlag != 4 ) {
         return 0;
     }
 
-    myPID = ( int ) getpid();
-    myHostName[0] = '\0';
-    gethostname( myHostName, MAX_NAME_LEN );
+    myPID = getpid();
+    std::memset(myHostName, 0, sizeof(myHostName));
+    const auto hostname = irods::get_server_property<std::string>(irods::KW_CFG_HOST);
+    hostname.copy(myHostName, sizeof(myHostName) - 1);
path: plugins/rule_engines/irods_rule_language/src/nre.reHelpers1.cpp
user: login: trel
body: sold.  resolving.
created_at: 2025-03-28T14:22:18Z
author_association: MEMBER
diff_hunk: @@ -103,7 +103,11 @@
             "type": "integer",
             "minimum": 0
         },
-        "host": {"type": "string"},
+        "host": {
+            "type": "string",
+            "minLength": 1,
+            "maxLength": 256
path: schemas/configuration/v5/server_config.json.in
user: login: korydraughn
body: Change to 255.
created_at: 2025-03-29T17:50:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -103,7 +103,11 @@
             "type": "integer",
             "minimum": 0
         },
-        "host": {"type": "string"},
+        "host": {
+            "type": "string",
+            "minLength": 1,
+            "maxLength": 256
path: schemas/configuration/v5/server_config.json.in
user: login: korydraughn
body: Add a test proving the length requirement is enforced.
created_at: 2025-03-29T17:52:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -103,7 +103,11 @@
             "type": "integer",
             "minimum": 0
         },
-        "host": {"type": "string"},
+        "host": {
+            "type": "string",
+            "minLength": 1,
+            "maxLength": 256
path: schemas/configuration/v5/server_config.json.in
user: login: trel
body: and please try both 255 and 256 (boundaries)
created_at: 2025-03-29T17:53:03Z
author_association: MEMBER
diff_hunk: @@ -103,7 +103,11 @@
             "type": "integer",
             "minimum": 0
         },
-        "host": {"type": "string"},
+        "host": {
+            "type": "string",
+            "minLength": 1,
+            "maxLength": 256
path: schemas/configuration/v5/server_config.json.in
user: login: korydraughn
body: Done.

Changed maxLength to 253 since that is the true usable character limit.
created_at: 2025-03-29T20:10:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -103,7 +103,11 @@
             "type": "integer",
             "minimum": 0
         },
-        "host": {"type": "string"},
+        "host": {
+            "type": "string",
+            "minLength": 1,
+            "maxLength": 256
path: schemas/configuration/v5/server_config.json.in
user: login: trel
body: oh?!  why?   if anything, i'd have expected 254 plus null b/c the spec might say 255...
created_at: 2025-03-29T20:11:48Z
author_association: MEMBER
diff_hunk: @@ -477,3 +479,33 @@ def test_logical_path_including_the_AND_keyword_SPACES_and_a_SINGLE_QUOTATION_MA
         finally:
             if os.path.exists(filename):
                 os.unlink(filename)
+
+    @unittest.skipIf(test.settings.RUN_IN_TOPOLOGY, 'Only requires a single server')
+    def test_configuration_validation_reports_fqdn_size_violations__issue_8287(self):
+        config = IrodsConfig()
+
+        with lib.file_backed_up(config.server_config_path):
+            with self.subTest('"host" property is empty'):
path: scripts/irods/test/test_misc.py
user: login: korydraughn
body: empty -> empty string
created_at: 2025-03-29T20:11:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -103,7 +103,11 @@
             "type": "integer",
             "minimum": 0
         },
-        "host": {"type": "string"},
+        "host": {
+            "type": "string",
+            "minLength": 1,
+            "maxLength": 256
path: schemas/configuration/v5/server_config.json.in
user: login: trel
body: ah, behold.   learned something (again).

https://web.archive.org/web/20190518124533/https://devblogs.microsoft.com/oldnewthing/?p=7873
created_at: 2025-03-29T20:14:35Z
author_association: MEMBER
diff_hunk: @@ -477,3 +479,33 @@ def test_logical_path_including_the_AND_keyword_SPACES_and_a_SINGLE_QUOTATION_MA
         finally:
             if os.path.exists(filename):
                 os.unlink(filename)
+
+    @unittest.skipIf(test.settings.RUN_IN_TOPOLOGY, 'Only requires a single server')
+    def test_configuration_validation_reports_fqdn_size_violations__issue_8287(self):
+        config = IrodsConfig()
+
+        with lib.file_backed_up(config.server_config_path):
+            with self.subTest('"host" property is empty'):
path: scripts/irods/test/test_misc.py
user: login: trel
body: 'an empty string'
created_at: 2025-03-29T20:14:52Z
author_association: MEMBER
diff_hunk: @@ -477,3 +479,33 @@ def test_logical_path_including_the_AND_keyword_SPACES_and_a_SINGLE_QUOTATION_MA
         finally:
             if os.path.exists(filename):
                 os.unlink(filename)
+
+    @unittest.skipIf(test.settings.RUN_IN_TOPOLOGY, 'Only requires a single server')
+    def test_configuration_validation_reports_fqdn_size_violations__issue_8287(self):
+        config = IrodsConfig()
path: scripts/irods/test/test_misc.py
user: login: trel
body: consider leaving this link here in a comment to explain the 253...

https://web.archive.org/web/20190518124533/https://devblogs.microsoft.com/oldnewthing/?p=7873
created_at: 2025-03-29T20:15:50Z
author_association: MEMBER
diff_hunk: @@ -477,3 +479,33 @@ def test_logical_path_including_the_AND_keyword_SPACES_and_a_SINGLE_QUOTATION_MA
         finally:
             if os.path.exists(filename):
                 os.unlink(filename)
+
+    @unittest.skipIf(test.settings.RUN_IN_TOPOLOGY, 'Only requires a single server')
+    def test_configuration_validation_reports_fqdn_size_violations__issue_8287(self):
+        config = IrodsConfig()
+
+        with lib.file_backed_up(config.server_config_path):
+            with self.subTest('"host" property is empty'):
path: scripts/irods/test/test_misc.py
user: login: korydraughn
body: Done.
created_at: 2025-03-29T20:28:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -477,3 +479,33 @@ def test_logical_path_including_the_AND_keyword_SPACES_and_a_SINGLE_QUOTATION_MA
         finally:
             if os.path.exists(filename):
                 os.unlink(filename)
+
+    @unittest.skipIf(test.settings.RUN_IN_TOPOLOGY, 'Only requires a single server')
+    def test_configuration_validation_reports_fqdn_size_violations__issue_8287(self):
+        config = IrodsConfig()
path: scripts/irods/test/test_misc.py
user: login: korydraughn
body: Done.
created_at: 2025-03-29T20:28:43Z
author_association: CONTRIBUTOR

PR comments:
user: login: korydraughn
created_at: 2025-03-29T20:51:45Z
body: The C++ code changes have passed unit and core tests. I'm going to run the changes against the federation and topology tests to see if anything is broken.

The new python tests passed in isolation.
author_association: CONTRIBUTOR
user: login: korydraughn
created_at: 2025-03-29T21:21:59Z
body: Federation tests passed.

Running topology tests for consumer.
author_association: CONTRIBUTOR
user: login: korydraughn
created_at: 2025-03-30T02:02:27Z
body: All topology/consumer tests passed except for some due to things that have already been captured in issues.

Squashing.
author_association: CONTRIBUTOR
user: login: korydraughn
created_at: 2025-03-30T02:04:18Z
body: Squashed.
author_association: CONTRIBUTOR
user: login: korydraughn
created_at: 2025-03-31T14:11:01Z
body: Pounded.
author_association: CONTRIBUTOR