Commit 6758bc02 authored by Geoff Simmons's avatar Geoff Simmons Committed by Dridi Boukelmoune

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.
parent bf1d9979
...@@ -335,6 +335,126 @@ mcf_param_show(struct cli *cli, const char * const *av, void *priv) ...@@ -335,6 +335,126 @@ mcf_param_show(struct cli *cli, const char * const *av, void *priv)
VSB_destroy(&vsb); 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 * Mark parameters as protected
*/ */
...@@ -471,7 +591,8 @@ mcf_wash_param(struct cli *cli, const struct parspec *pp, const char **val, ...@@ -471,7 +591,8 @@ mcf_wash_param(struct cli *cli, const struct parspec *pp, const char **val,
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static struct cli_proto cli_params[] = { 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 }, { CLICMD_PARAM_SET, "", mcf_param_set },
{ NULL } { NULL }
}; };
......
...@@ -32,6 +32,9 @@ struct parspec; ...@@ -32,6 +32,9 @@ struct parspec;
typedef int tweak_t(struct vsb *, const struct parspec *, const char *arg); 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 { struct parspec {
const char *name; const char *name;
tweak_t *func; tweak_t *func;
......
...@@ -119,7 +119,7 @@ tweak_vsl_mask(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -119,7 +119,7 @@ tweak_vsl_mask(struct vsb *vsb, const struct parspec *par, const char *arg)
const char *s; const char *s;
(void)par; (void)par;
if (arg != NULL) { if (arg != NULL && arg != JSON_FMT) {
if (!strcmp(arg, "default")) { if (!strcmp(arg, "default")) {
memset(mgt_param.vsl_mask, memset(mgt_param.vsl_mask,
0, sizeof 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) ...@@ -141,6 +141,8 @@ tweak_vsl_mask(struct vsb *vsb, const struct parspec *par, const char *arg)
"VSL tag", "-")); "VSL tag", "-"));
} }
} else { } else {
if (arg == JSON_FMT)
VSB_putc(vsb, '"');
s = ""; s = "";
for (j = 0; j < (unsigned)SLT__Reserved; j++) { for (j = 0; j < (unsigned)SLT__Reserved; j++) {
if (bit(mgt_param.vsl_mask, j, BTST)) { 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) ...@@ -150,6 +152,8 @@ tweak_vsl_mask(struct vsb *vsb, const struct parspec *par, const char *arg)
} }
if (*s == '\0') if (*s == '\0')
VSB_printf(vsb, "(all enabled)"); VSB_printf(vsb, "(all enabled)");
if (arg == JSON_FMT)
VSB_putc(vsb, '"');
} }
return (0); return (0);
} }
...@@ -171,7 +175,7 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -171,7 +175,7 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg)
unsigned j; unsigned j;
(void)par; (void)par;
if (arg != NULL) { if (arg != NULL && arg != JSON_FMT) {
if (!strcmp(arg, "none")) { if (!strcmp(arg, "none")) {
memset(mgt_param.debug_bits, memset(mgt_param.debug_bits,
0, sizeof 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) ...@@ -180,6 +184,8 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg)
DBG_Reserved, arg, debug_tags, "debug bit", "+")); DBG_Reserved, arg, debug_tags, "debug bit", "+"));
} }
} else { } else {
if (arg == JSON_FMT)
VSB_putc(vsb, '"');
s = ""; s = "";
for (j = 0; j < (unsigned)DBG_Reserved; j++) { for (j = 0; j < (unsigned)DBG_Reserved; j++) {
if (bit(mgt_param.debug_bits, j, BTST)) { if (bit(mgt_param.debug_bits, j, BTST)) {
...@@ -189,6 +195,8 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -189,6 +195,8 @@ tweak_debug(struct vsb *vsb, const struct parspec *par, const char *arg)
} }
if (*s == '\0') if (*s == '\0')
VSB_printf(vsb, "none"); VSB_printf(vsb, "none");
if (arg == JSON_FMT)
VSB_putc(vsb, '"');
} }
return (0); return (0);
} }
...@@ -210,7 +218,7 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -210,7 +218,7 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg)
unsigned j; unsigned j;
(void)par; (void)par;
if (arg != NULL) { if (arg != NULL && arg != JSON_FMT) {
if (!strcmp(arg, "none")) { if (!strcmp(arg, "none")) {
memset(mgt_param.feature_bits, memset(mgt_param.feature_bits,
0, sizeof 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) ...@@ -220,6 +228,8 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg)
"feature bit", "+")); "feature bit", "+"));
} }
} else { } else {
if (arg == JSON_FMT)
VSB_putc(vsb, '"');
s = ""; s = "";
for (j = 0; j < (unsigned)FEATURE_Reserved; j++) { for (j = 0; j < (unsigned)FEATURE_Reserved; j++) {
if (bit(mgt_param.feature_bits, j, BTST)) { if (bit(mgt_param.feature_bits, j, BTST)) {
...@@ -229,6 +239,8 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -229,6 +239,8 @@ tweak_feature(struct vsb *vsb, const struct parspec *par, const char *arg)
} }
if (*s == '\0') if (*s == '\0')
VSB_printf(vsb, "none"); VSB_printf(vsb, "none");
if (arg == JSON_FMT)
VSB_putc(vsb, '"');
} }
return (0); return (0);
} }
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#include "vav.h" #include "vav.h"
#include "vnum.h" #include "vnum.h"
const char * const JSON_FMT = (const char *)&JSON_FMT;
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Generic handling of double typed parameters * Generic handling of double typed parameters
*/ */
...@@ -53,7 +55,7 @@ tweak_generic_double(struct vsb *vsb, volatile double *dest, ...@@ -53,7 +55,7 @@ tweak_generic_double(struct vsb *vsb, volatile double *dest,
{ {
volatile double u, minv = 0, maxv = 0; volatile double u, minv = 0, maxv = 0;
if (arg != NULL) { if (arg != NULL && arg != JSON_FMT) {
if (min != NULL) { if (min != NULL) {
minv = VNUM(min); minv = VNUM(min);
if (isnan(minv)) { if (isnan(minv)) {
...@@ -123,7 +125,7 @@ tweak_bool(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -123,7 +125,7 @@ tweak_bool(struct vsb *vsb, const struct parspec *par, const char *arg)
volatile unsigned *dest; volatile unsigned *dest;
dest = par->priv; dest = par->priv;
if (arg != NULL) { if (arg != NULL && arg != JSON_FMT) {
if (!strcasecmp(arg, "off")) if (!strcasecmp(arg, "off"))
*dest = 0; *dest = 0;
else if (!strcasecmp(arg, "disable")) else if (!strcasecmp(arg, "disable"))
...@@ -144,6 +146,8 @@ tweak_bool(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -144,6 +146,8 @@ tweak_bool(struct vsb *vsb, const struct parspec *par, const char *arg)
VSB_printf(vsb, "use \"on\" or \"off\"\n"); VSB_printf(vsb, "use \"on\" or \"off\"\n");
return (-1); return (-1);
} }
} else if (arg == JSON_FMT) {
VSB_printf(vsb, "%s", *dest ? "true" : "false");
} else { } else {
VSB_printf(vsb, "%s", *dest ? "on" : "off"); VSB_printf(vsb, "%s", *dest ? "on" : "off");
} }
...@@ -159,7 +163,7 @@ tweak_generic_uint(struct vsb *vsb, volatile unsigned *dest, const char *arg, ...@@ -159,7 +163,7 @@ tweak_generic_uint(struct vsb *vsb, volatile unsigned *dest, const char *arg,
unsigned u, minv = 0, maxv = 0; unsigned u, minv = 0, maxv = 0;
char *p; char *p;
if (arg != NULL) { if (arg != NULL && arg != JSON_FMT) {
if (min != NULL) { if (min != NULL) {
p = NULL; p = NULL;
minv = strtoul(min, &p, 0); minv = strtoul(min, &p, 0);
...@@ -195,7 +199,7 @@ tweak_generic_uint(struct vsb *vsb, volatile unsigned *dest, const char *arg, ...@@ -195,7 +199,7 @@ tweak_generic_uint(struct vsb *vsb, volatile unsigned *dest, const char *arg,
return (-1); return (-1);
} }
*dest = u; *dest = u;
} else if (*dest == UINT_MAX) { } else if (*dest == UINT_MAX && arg != JSON_FMT) {
VSB_printf(vsb, "unlimited"); VSB_printf(vsb, "unlimited");
} else { } else {
VSB_printf(vsb, "%u", *dest); VSB_printf(vsb, "%u", *dest);
...@@ -246,7 +250,7 @@ tweak_generic_bytes(struct vsb *vsb, volatile ssize_t *dest, const char *arg, ...@@ -246,7 +250,7 @@ tweak_generic_bytes(struct vsb *vsb, volatile ssize_t *dest, const char *arg,
uintmax_t r, rmin = 0, rmax = 0; uintmax_t r, rmin = 0, rmax = 0;
const char *p; const char *p;
if (arg != NULL) { if (arg != NULL && arg != JSON_FMT) {
if (min != NULL) { if (min != NULL) {
p = VNUM_2bytes(min, &rmin, 0); p = VNUM_2bytes(min, &rmin, 0);
if (p != NULL) { if (p != NULL) {
...@@ -285,6 +289,8 @@ tweak_generic_bytes(struct vsb *vsb, volatile ssize_t *dest, const char *arg, ...@@ -285,6 +289,8 @@ tweak_generic_bytes(struct vsb *vsb, volatile ssize_t *dest, const char *arg,
return (-1); return (-1);
} }
*dest = r; *dest = r;
} else if (arg == JSON_FMT) {
VSB_printf(vsb, "%zd", *dest);
} else { } else {
fmt_bytes(vsb, *dest); fmt_bytes(vsb, *dest);
} }
...@@ -364,6 +370,8 @@ tweak_string(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -364,6 +370,8 @@ tweak_string(struct vsb *vsb, const struct parspec *par, const char *arg)
/* XXX should have tweak_generic_string */ /* XXX should have tweak_generic_string */
if (arg == NULL) { if (arg == NULL) {
VSB_quote(vsb, *p, -1, 0); VSB_quote(vsb, *p, -1, 0);
} else if (arg == JSON_FMT) {
VSB_quote(vsb, *p, -1, VSB_QUOTE_JSON|VSB_QUOTE_CSTR);
} else { } else {
REPLACE(*p, arg); REPLACE(*p, arg);
} }
...@@ -380,7 +388,15 @@ tweak_poolparam(struct vsb *vsb, const struct parspec *par, const char *arg) ...@@ -380,7 +388,15 @@ tweak_poolparam(struct vsb *vsb, const struct parspec *par, const char *arg)
int retval = 0; int retval = 0;
pp = par->priv; 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", VSB_printf(vsb, "%u,%u,%g",
pp->min_pool, pp->max_pool, pp->max_age); pp->min_pool, pp->max_pool, pp->max_age);
} else { } else {
......
...@@ -33,3 +33,10 @@ varnish v1 -clierr "106" {param.show fofofofo} ...@@ -33,3 +33,10 @@ varnish v1 -clierr "106" {param.show fofofofo}
varnish v1 -cliok "param.show changed" varnish v1 -cliok "param.show changed"
varnish v1 -cliok "param.show " varnish v1 -cliok "param.show "
varnish v1 -cliok "param.show -l" 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"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment