]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy: define "add backend" handler
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 17 Dec 2025 09:57:40 +0000 (10:57 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 6 Feb 2026 16:26:55 +0000 (17:26 +0100)
Define a basic CLI handler for "add backend".

For now, this handler only performs a parsing of the name argument and
return an error if a duplicate already exists. It runs under thread
isolation, to guarantee thread safety during the proxy creation.

This feature is considered in development. CLI command requires to set
experimental-mode.

doc/management.txt
src/proxy.c

index b2b1d539d30781484d6c401187f1349cb5a57875..b07f287baa7909614b32ad0a779271a92197b5cb 100644 (file)
@@ -1725,6 +1725,19 @@ add acl [@<ver>] <acl> <pattern>
   This command cannot be used if the reference <acl> is a name also used with
   a map. In this case, the "add map" command must be used instead.
 
+add backend <name> from <defproxy> [ EXPERIMENTAL ]
+  Instantiate a new backend proxy with the name <name>.
+
+  Only TCP or HTTP proxies can be created. All of the settings are inherited
+  from <defproxy> default proxy instance. Servers can be added via the command
+  "add server". The backend is initialized in the unpublished state. Once
+  considered ready for traffic, use "publish backend" to expose the newly
+  created instance.
+
+  This command is restricted and can only be issued on sockets configured for
+  level "admin". Moreover, this feature is still considered in development so it
+  also requires experimental mode (see "experimental-mode on").
+
 add map [@<ver>] <map> <key> <value>
 add map [@<ver>] <map> <payload>
   Add an entry into the map <map> to associate the value <value> to the key
index 207f85a98d7446727173087b01b4b5aeb7c3ce8b..3d9f9440ba3291c6760b6bacfcf1665cd2adc939 100644 (file)
@@ -61,6 +61,7 @@
 #include <haproxy/stream.h>
 #include <haproxy/task.h>
 #include <haproxy/tcpcheck.h>
+#include <haproxy/thread.h>
 #include <haproxy/time.h>
 #include <haproxy/tools.h>
 #include <haproxy/uri_auth.h>
@@ -4777,6 +4778,70 @@ static int cli_parse_shutdown_frontend(char **args, char *payload, struct appctx
        return 1;
 }
 
+/* Parses a "add backend" CLI command to allocate a new backend instance,
+ * derived from a default proxy instance. This operation is performed under
+ * thread isolation.
+ *
+ * Always returns 1.
+ */
+static int cli_parse_add_backend(char **args, char *payload, struct appctx *appctx, void *private)
+{
+       struct proxy *px, *defpx;
+       const char *be_name, *def_name, *err;
+       char *msg = NULL;
+
+       usermsgs_clr("CLI");
+
+       if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
+               return 1;
+
+       ++args;
+       be_name = args[1];
+       if (!*be_name) {
+               cli_err(appctx, "Require backend name.\n");
+               return 1;
+       }
+       if ((err = invalid_char(be_name))) {
+               cli_dynerr(appctx, memprintf(&msg, "Invalid character '%c' in backend name.\n", *err));
+               return 1;
+       }
+
+       ++args;
+       def_name = args[2];
+       if (!*args[1] || !*def_name || strcmp(args[1], "from") != 0) {
+               cli_err(appctx, "Usage: add backend <name> from <defproxy>.\n");
+               return 1;
+       }
+
+       defpx = proxy_find_by_name(def_name, PR_CAP_DEF, 0);
+       if (!defpx) {
+               cli_dynerr(appctx, memprintf(&msg, "Cannot find default proxy '%s'.\n", def_name));
+               return 1;
+       }
+
+       thread_isolate();
+
+       if ((px = proxy_find_by_name(be_name, PR_CAP_NONE, 0)) ||
+           (px = proxy_find_by_name(be_name, PR_CAP_DEF, 0))) {
+               memprintf(&msg,
+                 "name is already used by other proxy '%s %s'",
+                 proxy_cap_str(px->cap), be_name);
+               px = NULL;
+               goto err;
+       }
+
+       thread_release();
+       ha_notice("New backend registered.\n");
+       cli_umsg(appctx, LOG_INFO);
+       return 1;
+
+ err:
+       thread_release();
+       if (msg)
+               cli_dynerr(appctx, msg);
+       return 1;
+}
+
 /* Parses the "disable frontend" directive, it always returns 1.
  *
  * Grabs the proxy lock.
@@ -5098,6 +5163,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
 
 /* register cli keywords */
 static struct cli_kw_list cli_kws = {{ },{
+       { { "add", "backend", NULL },                       "add backend <backend>                   : add a new backend",                                              cli_parse_add_backend, NULL, NULL, NULL, ACCESS_EXPERIMENTAL },
        { { "disable", "frontend",  NULL },                 "disable frontend <frontend>             : temporarily disable specific frontend",                          cli_parse_disable_frontend, NULL, NULL },
        { { "enable", "frontend",  NULL },                  "enable frontend <frontend>              : re-enable specific frontend",                                    cli_parse_enable_frontend, NULL, NULL },
        { { "publish", "backend",  NULL },                  "publish backend <backend>               : mark backend as ready for traffic",                              cli_parse_publish_backend, NULL, NULL },