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)
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 }
};
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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 {
......
......@@ -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"
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