From 2423ac26f56ecbf5dabe4624b124e84ccbe9f49a Mon Sep 17 00:00:00 2001
From: Joseph Lynch <joe.e.lynch@gmail.com>
Date: Wed, 21 Jun 2017 18:44:51 -0700
Subject: [PATCH] MINOR: cli: ability to change a server's name

This extends the "set server" socket command to also allow setting the
name for a server. This allows tools to introspect those names and
allows users of the stats page to have human readable names even when
they are dynamically updating backends.
---
 doc/management.txt     |  4 ++++
 include/proto/server.h |  1 +
 src/server.c           | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/doc/management.txt b/doc/management.txt
index df091bb..9ca959c 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -1665,6 +1665,10 @@ set server <backend>/<server> weight <weight>[%]
 set server <backend>/<server> fqdn <FQDN>
   Change a server's FQDN to the value passed in argument.
 
+set server <backend>/<server> name <name>
+  Change a server's name to <name>. This updates the name displayed in the
+  stats socket, stats page, logs, etc ...
+
 set ssl ocsp-response <response>
   This command is used to update an OCSP Response for a certificate (see "crt"
   on "bind" lines). Same controls are performed as during the initial loading of
diff --git a/include/proto/server.h b/include/proto/server.h
index 43e4e42..027018d 100644
--- a/include/proto/server.h
+++ b/include/proto/server.h
@@ -42,6 +42,7 @@ int srv_getinter(const struct check *check);
 int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy);
 int update_server_addr(struct server *s, void *ip, int ip_sin_family, const char *updater);
 const char *update_server_addr_port(struct server *s, const char *addr, const char *port, char *updater);
+const char *update_server_name(struct server *server, const char *name, const char *updater);
 struct server *server_find_by_id(struct proxy *bk, int id);
 struct server *server_find_by_name(struct proxy *bk, const char *name);
 struct server *server_find_best_match(struct proxy *bk, char *name, int id, int *diff);
diff --git a/src/server.c b/src/server.c
index 008bafa..8ff804d 100644
--- a/src/server.c
+++ b/src/server.c
@@ -4190,6 +4190,39 @@ int srv_init_addr(void)
 	return return_code;
 }
 
+const char *update_server_name(struct server *server, const char *name, const char *updater)
+{
+	struct chunk *msg;
+
+	msg = get_trash_chunk();
+	chunk_reset(msg);
+
+	if (!strcmp(name, server->id)) {
+		chunk_appendf(msg, "no need to change the name");
+		goto out;
+	}
+
+	char* old_name = server->id;
+	server->id = strdup(name);
+	if (!server->id) {
+		server->id = old_name;
+		chunk_reset(msg);
+		chunk_appendf(msg, "could not update %s/%s name",
+		              server->proxy->id, server->id);
+	} else {
+		chunk_appendf(msg, "%s/%s changed its name from %s to %s",
+		              server->proxy->id, old_name, old_name, name);
+		free(old_name);
+	}
+
+out:
+	if (updater)
+		chunk_appendf(msg, " by '%s'", updater);
+	chunk_appendf(msg, "\n");
+
+	return msg->str;
+}
+
 const char *update_server_fqdn(struct server *server, const char *fqdn, const char *updater)
 {
 
@@ -4422,8 +4455,20 @@ static int cli_parse_set_server(char **args, struct appctx *appctx, void *privat
 			appctx->st0 = CLI_ST_PRINT;
 		}
 	}
+	else if (strcmp(args[3], "name") == 0) {
+		if (!*args[4]) {
+			appctx->ctx.cli.msg = "set server <b>/<s> name requires a name.\n";
+			appctx->st0 = CLI_ST_PRINT;
+			return 1;
+		}
+		warning = update_server_name(sv, args[4], "stats socket command");
+		if (warning) {
+			appctx->ctx.cli.msg = warning;
+			appctx->st0 = CLI_ST_PRINT;
+		}
+	}
 	else {
-		appctx->ctx.cli.msg = "'set server <srv>' only supports 'agent', 'health', 'state', 'weight', 'addr', 'fqdn' and 'check-port'.\n";
+		appctx->ctx.cli.msg = "'set server <srv>' only supports 'agent', 'health', 'state', 'weight', 'addr', 'fqdn', 'name', and 'check-port'.\n";
 		appctx->st0 = CLI_ST_PRINT;
 	}
 	return 1;
-- 
2.4.5

