]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: server: refactor cli_find_server()
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 10 Sep 2026 09:11:42 +0000 (11:11 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 14 Oct 2026 09:15:39 +0000 (11:15 +0200)
Refactor cli_find_server() by splitting its execution into two separated
functions. The first one parse_be_srv() is able to extract a backend and
server name from an argument of the form <bename>/<svname>. The second
function find_be_srv() is responsible to perform the lookup of a server
using a backend and server name.

Now cli_find_server() consists mainly of these two calls. The objective
is to be able to perform only the parsing or lookup parts, without
automatic CLI error display. This will be used to extend CLI "wait"
command handler.

CLI parser "delete server" has been updated to use the new
parse_be_srv() as an example of usage. In the future, it could be useful
to update all similar handlers relying on the same argument format.

include/haproxy/server.h
src/server.c

index 97d3a1db233780f1b17392a634ea165ce32b61cb..b0c9526c5ad9e2842629df084638fd37931ecdec 100644 (file)
@@ -77,7 +77,13 @@ void srv_compute_all_admin_states(struct proxy *px);
 int srv_set_addr_via_libc(struct server *srv, int *err_code);
 int srv_postinit(struct server *srv);
 int srv_init_addr(void);
+
+int parse_be_srv(char *arg, const char **bename, const char **svname,
+                 const char **msg);
+struct server *find_be_srv(const char *bename, const char *svname,
+                           const char **msg);
 struct server *cli_find_server(struct appctx *appctx, char *arg);
+
 int cli_clear_counters_server(struct appctx *appctx, char *arg, int force);
 struct server *new_server(struct proxy *proxy);
 void srv_take(struct server *srv);
index 3d1c390e05c4d30d0e5a8255ff969eaf51f6f0d7..6bc9f34901927195604106069ca79ad15f294b70 100644 (file)
@@ -5867,39 +5867,77 @@ static const char *srv_update_server_name(struct server *srv, const char *new_na
        return NULL;
 }
 
+/* Parses <arg> as the form 'backend'/'server' and update output parameters
+ * <bename> and <svname> with the extracted values. In case the argument is
+ * malformed, <msg> will point to the error description.
+ *
+ * Note that <arg> input string is modified as '/' separator is blanked.
+ *
+ * Returns 0 on success, non-zero if argument is malformed.
+ */
+int parse_be_srv(char *arg, const char **bename, const char **svname,
+                 const char **msg)
+{
+       struct ist ist_be, ist_sv = ist(arg);
+
+       ist_be = istsplit(&ist_sv, '/');
+       if (!istlen(ist_sv)) {
+               *msg = "Require 'backend/server'.\n";
+               return 1;
+       }
+
+       *bename = ist0(ist_be);
+       *svname = ist0(ist_sv);
+       return 0;
+}
 
-/* Expects to find a backend and a server in <arg> under the form <backend>/<server>,
- * and returns the pointer to the server. Otherwise, display adequate error messages
- * on the CLI, sets the CLI's state to CLI_ST_PRINT and returns NULL. This is only
- * used for CLI commands requiring a server name.
- * Important: the <arg> is modified to remove the '/'.
+/* Lookup a server instance named <svname> in proxy named <bename>. If the
+ * server is not found, <msg> will point to the error description.
+ *
+ * Returns the found server or NULL.
  */
-struct server *cli_find_server(struct appctx *appctx, char *arg)
+struct server *find_be_srv(const char *bename, const char *svname,
+                           const char **msg)
 {
        struct proxy *px;
        struct server *sv;
-       struct ist be_name, sv_name = ist(arg);
 
-       be_name = istsplit(&sv_name, '/');
-       if (!istlen(sv_name)) {
-               cli_err(appctx, "Require 'backend/server'.\n");
+       if (!(px = proxy_be_by_name(bename))) {
+               *msg = "No such backend.\n";
                return NULL;
        }
-
-       if (!(px = proxy_be_by_name(ist0(be_name)))) {
-               cli_err(appctx, "No such backend.\n");
+       if (!(sv = server_find(px, svname))) {
+               *msg = "No such server.\n";
                return NULL;
        }
-       if (!(sv = server_find(px, ist0(sv_name)))) {
-               cli_err(appctx, "No such server.\n");
+
+       if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) {
+               *msg = "Proxy is disabled.\n";
                return NULL;
        }
 
-       if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) {
-               cli_err(appctx, "Proxy is disabled.\n");
+       return sv;
+}
+
+/* High-level server parsing function for server lookup using <arg> argument of
+ * the form 'backend'/'server'. As an extra convenience, error message is
+ * printed on CLI output if argument is malformed or server instance not found.
+ *
+ * Returns the found server or NULL.
+ */
+struct server *cli_find_server(struct appctx *appctx, char *arg)
+{
+       struct server *sv;
+       const char *bename, *svname, *msg;
+
+       if (parse_be_srv(arg, &bename, &svname, &msg)) {
+               cli_err(appctx, msg);
                return NULL;
        }
 
+       sv = find_be_srv(bename, svname, &msg);
+       if (!sv)
+               cli_err(appctx, msg);
        return sv;
 }
 
@@ -6948,9 +6986,8 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap
 {
        struct proxy *be;
        struct server *srv, *next;
-       struct ist be_name, sv_name;
        struct watcher *srv_watch;
-       const char *msg;
+       const char *be_name, *sv_name, *msg;
        int ret;
 
        if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
@@ -6966,14 +7003,12 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap
         */
        thread_isolate_full();
 
-       sv_name = ist(args[1]);
-       be_name = istsplit(&sv_name, '/');
-       if (!istlen(sv_name)) {
-               cli_err(appctx, "Require 'backend/server'.\n");
+       if (parse_be_srv(args[1], &be_name, &sv_name, &msg)) {
+               cli_err(appctx, msg);
                goto out;
        }
 
-       ret = srv_check_for_deletion(ist0(be_name), ist0(sv_name), &be, &srv, &msg);
+       ret = srv_check_for_deletion(be_name, sv_name, &be, &srv, &msg);
        if (ret <= 0) {
                /* failure (recoverable or not) */
                cli_err(appctx, msg);