[master] db0e25961 Add JSON support for the "param.show" CLI command.
Geoff Simmons
geoff at uplex.de
Mon Oct 8 11:28:12 UTC 2018
commit db0e25961e424411c596f642cdbc84919621b685
Author: Geoff Simmons <geoff at uplex.de>
Date: Mon Sep 24 17:51:01 2018 +0200
Add JSON support for the "param.show" CLI command.
* Each param is represented as a JSON object listed in the output
array.
* The object's "value" field contains the current value, which can
have different types -- int, float, string or boolean.
* There is no -l form with param.show -j, each object contains the
full description.
* But "param.show -j the_param" or "param.show -j changed" may be
used to limit the number of objects in the output.
* Each object may or may not have any of the fields "minimum",
"maximum", "default" or "units", depending on the param.
* Params not implemented on the present platform just have
"implemented":false along with the param name, and no other fields.
* The values of the "minimum", "maximum" and "default" fields are
always strings.
diff --git a/bin/varnishd/mgt/mgt_param.c b/bin/varnishd/mgt/mgt_param.c
index 139814c09..f3faa9cb3 100644
--- a/bin/varnishd/mgt/mgt_param.c
+++ b/bin/varnishd/mgt/mgt_param.c
@@ -335,6 +335,126 @@ mcf_param_show(struct cli *cli, const char * const *av, void *priv)
VSB_destroy(&vsb);
}
+static inline void
+mcf_json_key_valstr(struct cli *cli, const char *key, const char *val)
+{
+ VCLI_Out(cli, "\"%s\": ", key);
+ VCLI_JSON_str(cli, val);
+ VCLI_Out(cli, ",\n");
+}
+
+static void v_matchproto_(cli_func_t)
+mcf_param_show_json(struct cli *cli, const char * const *av, void *priv)
+{
+ int n, comma = 0;
+ struct plist *pl;
+ const struct parspec *pp;
+ int chg = 0, flags;
+ struct vsb *vsb, *def;
+ const char *show = NULL;
+
+ vsb = VSB_new_auto();
+ def = VSB_new_auto();
+ (void)priv;
+
+ for (int i = 2; av[i] != NULL; i++) {
+ if (strcmp(av[i], "-l") == 0) {
+ VCLI_SetResult(cli, CLIS_PARAM);
+ VCLI_Out(cli, "-l not permitted with param.show -j");
+ return;
+ }
+ if (strcmp(av[i], "changed") == 0) {
+ chg = 1;
+ continue;
+ }
+ if (strcmp(av[i], "-j") == 0)
+ continue;
+ show = av[i];
+ }
+
+ n = 0;
+ VCLI_JSON_begin(cli, 2, av);
+ VCLI_Out(cli, ",\n");
+ VTAILQ_FOREACH(pl, &phead, list) {
+ pp = pl->spec;
+ if (show != NULL && strcmp(pp->name, show) != 0)
+ continue;
+ n++;
+
+ VSB_clear(vsb);
+ if (pp->func(vsb, pp, JSON_FMT))
+ VCLI_SetResult(cli, CLIS_PARAM);
+ AZ(VSB_finish(vsb));
+ VSB_clear(def);
+ if (pp->func(def, pp, NULL))
+ VCLI_SetResult(cli, CLIS_PARAM);
+ AZ(VSB_finish(def));
+ if (chg && pp->def != NULL && !strcmp(pp->def, VSB_data(def)))
+ continue;
+
+ VCLI_Out(cli, "%s", comma ? ",\n" : "");
+ comma++;
+ VCLI_Out(cli, "{\n");
+ VSB_indent(cli->sb, 2);
+ mcf_json_key_valstr(cli, "name", pp->name);
+ if (pp->flags & NOT_IMPLEMENTED) {
+ VCLI_Out(cli, "\"implemented\": false\n");
+ VSB_indent(cli->sb, -2);
+ VCLI_Out(cli, "}");
+ continue;
+ }
+ VCLI_Out(cli, "\"implemented\": true,\n");
+ VCLI_Out(cli, "\"value\": %s,\n", VSB_data(vsb));
+ if (pp->units != NULL && *pp->units != '\0')
+ mcf_json_key_valstr(cli, "units", pp->units);
+
+ if (pp->def != NULL)
+ mcf_json_key_valstr(cli, "default", pp->def);
+ if (pp->min != NULL)
+ mcf_json_key_valstr(cli, "minimum", pp->min);
+ if (pp->max != NULL)
+ mcf_json_key_valstr(cli, "maximum", pp->max);
+ mcf_json_key_valstr(cli, "description", pp->descr);
+
+ flags = 0;
+ VCLI_Out(cli, "\"flags\": [\n");
+ VSB_indent(cli->sb, 2);
+
+#define flag_out(flag, string) do { \
+ if (pp->flags & flag) { \
+ if (flags) \
+ VCLI_Out(cli, ",\n"); \
+ VCLI_Out(cli, "\"%s\"", #string); \
+ flags++; \
+ } \
+ } while(0)
+
+ flag_out(OBJ_STICKY, obj_sticky);
+ flag_out(DELAYED_EFFECT, delayed_effect);
+ flag_out(EXPERIMENTAL, experimental);
+ flag_out(MUST_RELOAD, must_reload);
+ flag_out(MUST_RESTART, must_restart);
+ flag_out(WIZARD, wizard);
+ flag_out(PROTECTED, protected);
+ flag_out(ONLY_ROOT, only_root);
+
+#undef flag_out
+
+ VSB_indent(cli->sb, -2);
+ VCLI_Out(cli, "\n]");
+ VSB_indent(cli->sb, -2);
+ VCLI_Out(cli, "\n}");
+ }
+ VCLI_JSON_end(cli);
+ if (show != NULL && n == 0) {
+ VSB_clear(cli->sb);
+ VCLI_SetResult(cli, CLIS_PARAM);
+ VCLI_Out(cli, "Unknown parameter \"%s\".", show);
+ }
+ VSB_destroy(&vsb);
+ VSB_destroy(&def);
+}
+
/*--------------------------------------------------------------------
* Mark parameters as protected
*/
@@ -471,7 +591,8 @@ mcf_wash_param(struct cli *cli, const struct parspec *pp, const char **val,
/*--------------------------------------------------------------------*/
static struct cli_proto cli_params[] = {
- { CLICMD_PARAM_SHOW, "", mcf_param_show },
+ { CLICMD_PARAM_SHOW, "", mcf_param_show,
+ mcf_param_show_json },
{ CLICMD_PARAM_SET, "", mcf_param_set },
{ NULL }
};
diff --git a/bin/varnishd/mgt/mgt_param.h b/bin/varnishd/mgt/mgt_param.h
index f4362ca96..7188b64e1 100644
--- a/bin/varnishd/mgt/mgt_param.h
+++ b/bin/varnishd/mgt/mgt_param.h
@@ -32,6 +32,9 @@ struct parspec;
typedef int tweak_t(struct vsb *, const struct parspec *, const char *arg);
+/* Sentinel for the arg position of tweak_t to ask for JSON formatting. */
+extern const char * const JSON_FMT;
+
struct parspec {
const char *name;
tweak_t *func;
diff --git a/bin/varnishd/mgt/mgt_param_bits.c b/bin/varnishd/mgt/mgt_param_bits.c
index a6d7b9216..263d8a34d 100644
--- a/bin/varnishd/mgt/mgt_param_bits.c
+++ b/bin/varnishd/mgt/mgt_param_bits.c
@@ -119,7 +119,7 @@ tweak_vsl_mask(struct vsb *vsb, const struct parspec *par, const char *arg)
const char *s;
(void)par;
- if (arg != NULL) {
+ if (arg != NULL && arg != JSON_FMT) {
if (!strcmp(arg, "default")) {
memset(mgt_param.vsl_mask,
0, sizeof mgt_param.vsl_mask);
@@ -141,6 +141,8 @@ tweak_vsl_mask(struct vsb *vsb, const struct parspec *par, const char *arg)
"VSL tag", "-"));
}
} else {
+ if (arg == JSON_FMT)
+ VSB_putc(vsb, '"');
s = "";
for (j = 0; j < (unsigned)SLT__Reserved; j++) {
if (bit(mgt_param.vsl_mask, j, BTST)) {
@@ -150,6 +152,8 @@ tweak_vsl_mask(struct vsb *vsb, const struct parspec *par, const char *arg)
}
if (*s == '\0')
VSB_printf(vsb, "(all enabled)");
+ if (arg == JSON_FMT)
+ VSB_putc(vsb, '"');
}
return (0);
}
@@ -171,7 +175,7 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg)
unsigned j;
(void)par;
- if (arg != NULL) {
+ if (arg != NULL && arg != JSON_FMT) {
if (!strcmp(arg, "none")) {
memset(mgt_param.debug_bits,
0, sizeof mgt_param.debug_bits);
@@ -180,6 +184,8 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg)
DBG_Reserved, arg, debug_tags, "debug bit", "+"));
}
} else {
+ if (arg == JSON_FMT)
+ VSB_putc(vsb, '"');
s = "";
for (j = 0; j < (unsigned)DBG_Reserved; j++) {
if (bit(mgt_param.debug_bits, j, BTST)) {
@@ -189,6 +195,8 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg)
}
if (*s == '\0')
VSB_printf(vsb, "none");
+ if (arg == JSON_FMT)
+ VSB_putc(vsb, '"');
}
return (0);
}
@@ -210,7 +218,7 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg)
unsigned j;
(void)par;
- if (arg != NULL) {
+ if (arg != NULL && arg != JSON_FMT) {
if (!strcmp(arg, "none")) {
memset(mgt_param.feature_bits,
0, sizeof mgt_param.feature_bits);
@@ -220,6 +228,8 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg)
"feature bit", "+"));
}
} else {
+ if (arg == JSON_FMT)
+ VSB_putc(vsb, '"');
s = "";
for (j = 0; j < (unsigned)FEATURE_Reserved; j++) {
if (bit(mgt_param.feature_bits, j, BTST)) {
@@ -229,6 +239,8 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg)
}
if (*s == '\0')
VSB_printf(vsb, "none");
+ if (arg == JSON_FMT)
+ VSB_putc(vsb, '"');
}
return (0);
}
diff --git a/bin/varnishd/mgt/mgt_param_tweak.c b/bin/varnishd/mgt/mgt_param_tweak.c
index 0f95237c2..01cab5f6b 100644
--- a/bin/varnishd/mgt/mgt_param_tweak.c
+++ b/bin/varnishd/mgt/mgt_param_tweak.c
@@ -43,6 +43,8 @@
#include "vav.h"
#include "vnum.h"
+const char * const JSON_FMT = (const char *)&JSON_FMT;
+
/*--------------------------------------------------------------------
* Generic handling of double typed parameters
*/
@@ -53,7 +55,7 @@ tweak_generic_double(struct vsb *vsb, volatile double *dest,
{
volatile double u, minv = 0, maxv = 0;
- if (arg != NULL) {
+ if (arg != NULL && arg != JSON_FMT) {
if (min != NULL) {
minv = VNUM(min);
if (isnan(minv)) {
@@ -123,7 +125,7 @@ tweak_bool(struct vsb *vsb, const struct parspec *par, const char *arg)
volatile unsigned *dest;
dest = par->priv;
- if (arg != NULL) {
+ if (arg != NULL && arg != JSON_FMT) {
if (!strcasecmp(arg, "off"))
*dest = 0;
else if (!strcasecmp(arg, "disable"))
@@ -144,6 +146,8 @@ tweak_bool(struct vsb *vsb, const struct parspec *par, const char *arg)
VSB_printf(vsb, "use \"on\" or \"off\"\n");
return (-1);
}
+ } else if (arg == JSON_FMT) {
+ VSB_printf(vsb, "%s", *dest ? "true" : "false");
} else {
VSB_printf(vsb, "%s", *dest ? "on" : "off");
}
@@ -159,7 +163,7 @@ tweak_generic_uint(struct vsb *vsb, volatile unsigned *dest, const char *arg,
unsigned u, minv = 0, maxv = 0;
char *p;
- if (arg != NULL) {
+ if (arg != NULL && arg != JSON_FMT) {
if (min != NULL) {
p = NULL;
minv = strtoul(min, &p, 0);
@@ -195,7 +199,7 @@ tweak_generic_uint(struct vsb *vsb, volatile unsigned *dest, const char *arg,
return (-1);
}
*dest = u;
- } else if (*dest == UINT_MAX) {
+ } else if (*dest == UINT_MAX && arg != JSON_FMT) {
VSB_printf(vsb, "unlimited");
} else {
VSB_printf(vsb, "%u", *dest);
@@ -246,7 +250,7 @@ tweak_generic_bytes(struct vsb *vsb, volatile ssize_t *dest, const char *arg,
uintmax_t r, rmin = 0, rmax = 0;
const char *p;
- if (arg != NULL) {
+ if (arg != NULL && arg != JSON_FMT) {
if (min != NULL) {
p = VNUM_2bytes(min, &rmin, 0);
if (p != NULL) {
@@ -285,6 +289,8 @@ tweak_generic_bytes(struct vsb *vsb, volatile ssize_t *dest, const char *arg,
return (-1);
}
*dest = r;
+ } else if (arg == JSON_FMT) {
+ VSB_printf(vsb, "%zd", *dest);
} else {
fmt_bytes(vsb, *dest);
}
@@ -364,6 +370,8 @@ tweak_string(struct vsb *vsb, const struct parspec *par, const char *arg)
/* XXX should have tweak_generic_string */
if (arg == NULL) {
VSB_quote(vsb, *p, -1, 0);
+ } else if (arg == JSON_FMT) {
+ VSB_quote(vsb, *p, -1, VSB_QUOTE_JSON|VSB_QUOTE_CSTR);
} else {
REPLACE(*p, arg);
}
@@ -380,7 +388,15 @@ tweak_poolparam(struct vsb *vsb, const struct parspec *par, const char *arg)
int retval = 0;
pp = par->priv;
- if (arg == NULL) {
+ if (arg == JSON_FMT) {
+ VSB_printf(vsb, "{\n");
+ VSB_indent(vsb, 8);
+ VSB_printf(vsb, "\"min_pool\": %u,\n", pp->min_pool);
+ VSB_printf(vsb, "\"max_pool\": %u,\n", pp->max_pool);
+ VSB_printf(vsb, "\"max_age\": %g\n", pp->max_age);
+ VSB_indent(vsb, -4);
+ VSB_printf(vsb, "}");
+ } else if (arg == NULL) {
VSB_printf(vsb, "%u,%u,%g",
pp->min_pool, pp->max_pool, pp->max_age);
} else {
diff --git a/bin/varnishtest/tests/b00042.vtc b/bin/varnishtest/tests/b00042.vtc
index 9fa143e9a..6470a7260 100644
--- a/bin/varnishtest/tests/b00042.vtc
+++ b/bin/varnishtest/tests/b00042.vtc
@@ -33,3 +33,10 @@ varnish v1 -clierr "106" {param.show fofofofo}
varnish v1 -cliok "param.show changed"
varnish v1 -cliok "param.show "
varnish v1 -cliok "param.show -l"
+
+varnish v1 -clijson "param.show -j pool_req"
+varnish v1 -clijson "param.show -j pool_sess"
+varnish v1 -clijson "param.show -j changed"
+varnish v1 -clijson "param.show -j"
+varnish v1 -clierr "106" "param.show -j -l"
+varnish v1 -clierr "106" "param.show -j fofofofo"
More information about the varnish-commit
mailing list