diff --git a/bin/varnishd/mgt/mgt.h b/bin/varnishd/mgt/mgt.h index 2610aaf752..6fcc211d02 100644 --- a/bin/varnishd/mgt/mgt.h +++ b/bin/varnishd/mgt/mgt.h @@ -199,6 +199,7 @@ void MCF_ParamConf(enum mcf_which_e, const char *param, const char *, ...) void MCF_ParamSet(struct cli *, const char *param, const char *val); void MCF_ParamProtect(struct cli *, const char *arg); void MCF_DumpRstParam(void); +void MCF_DumpJsonParam(void); extern struct params mgt_param; /* mgt_shmem.c */ diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c index 933a9d93a6..2329577a0e 100644 --- a/bin/varnishd/mgt/mgt_main.c +++ b/bin/varnishd/mgt/mgt_main.c @@ -138,7 +138,8 @@ usage(void) printf("\nDocumentation options:\n"); printf(FMT, "-?", "Prints this usage message"); - printf(FMT, "-x parameter", "Parameter documentation"); + printf(FMT, "-x parameter", "Parameter documentation in RST format"); + printf(FMT, "-x parameter-json", "Parameter documentation in JSON format"); printf(FMT, "-x vsl", "VSL record documentation"); printf(FMT, "-x cli", "CLI command documentation"); printf(FMT, "-x builtin", "Builtin VCL program"); @@ -378,6 +379,8 @@ mgt_x_arg(const char *x_arg) { if (!strcmp(x_arg, "parameter")) MCF_DumpRstParam(); + else if (!strcmp(x_arg, "parameter-json")) + MCF_DumpJsonParam(); else if (!strcmp(x_arg, "vsl")) mgt_DumpRstVsl(); else if (!strcmp(x_arg, "cli")) diff --git a/bin/varnishd/mgt/mgt_param.c b/bin/varnishd/mgt/mgt_param.c index 75491f695a..41593509b7 100644 --- a/bin/varnishd/mgt/mgt_param.c +++ b/bin/varnishd/mgt/mgt_param.c @@ -968,3 +968,84 @@ MCF_DumpRstParam(void) printf("\n\n"); } } + +void +MCF_DumpJsonParam(void) +{ + struct plist *pl; + const struct parspec *pp; + const char *p, *q; + unsigned flags; + struct vsb *vsb = VSB_new_auto(); + + CHECK_OBJ_NOTNULL(vsb, VSB_MAGIC); + + p = "\n"; + VSB_cat(vsb, "{"); + VSB_indent(vsb, 2); + VTAILQ_FOREACH(pl, &phead, list) { + pp = pl->spec; + if (!strcmp("deprecated_dummy", pp->name)) + continue; + + VSB_cat(vsb, p); + p = ",\n"; + VSB_cat(vsb, "\""); + VSB_quote(vsb, pp->name, -1, VSB_QUOTE_JSON); + VSB_cat(vsb, "\": {\n"); + VSB_indent(vsb, 2); + if (pp->flags & PLATFORM_DEPENDENT) + VSB_cat(vsb, "\"platformDependent\": true,\n"); + + if (pp->flags & BUILD_OPTIONS) + VSB_cat(vsb, "\"buildDependent\": true,\n"); + + if (pp->units != NULL && *pp->units != '\0') + VSB_printf(vsb, "\"units\": \"%s\",\n", pp->units); +#define MCF_DYN_REASON(lbl, nm) \ + if (pp->dyn_ ## nm ## _reason != NULL) \ + VSB_printf(vsb, "\"" #lbl "\": \"%s\",\n", \ + pp->dyn_ ## nm ## _reason); \ + else if (pp->nm != NULL) \ + VSB_printf(vsb, "\"" #lbl "\": \"%s\",\n", pp->nm); + MCF_DYN_REASON(default, def); + MCF_DYN_REASON(minimum, min); + MCF_DYN_REASON(maximum, max); +#undef MCF_DYN_REASON + flags = pp->flags & ~DOCS_FLAGS; + if (pp->func == tweak_timeout) + flags |= TYPE_TIMEOUT; + if (flags) { + q = "\n"; + VSB_cat(vsb, "\"flags\": ["); + VSB_indent(vsb, 2); +#define MCF_DYN_FLAGS(f, s) \ + if (flags & f) { \ + VSB_bcat(vsb, q, strlen(q)); \ + q = ",\n"; \ + VSB_printf(vsb, #s); \ + } + MCF_DYN_FLAGS(TYPE_TIMEOUT, "timeout"); + MCF_DYN_FLAGS(DELAYED_EFFECT, "delayed"); + MCF_DYN_FLAGS(MUST_RESTART, "must_restart"); + MCF_DYN_FLAGS(MUST_RELOAD, "smust_reload"); + MCF_DYN_FLAGS(EXPERIMENTAL, "experimental"); + MCF_DYN_FLAGS(WIZARD, "wizard"); + MCF_DYN_FLAGS(ONLY_ROOT, "only_root"); + MCF_DYN_FLAGS(OBJ_STICKY, "obj_sticky"); +#undef MCF_DYN_FLAGS + VSB_indent(vsb, -2); + VSB_cat(vsb, "\n],\n"); + } + VSB_cat(vsb, "\"description\": \""); + VSB_quote(vsb, pp->descr, -1, VSB_QUOTE_JSON); + VSB_bcat(vsb, "\"\n", 2); + VSB_indent(vsb, -2); + VSB_printf(vsb, "}"); + } + VSB_indent(vsb, -2); + VSB_cat(vsb, "\n}"); + AZ(VSB_finish(vsb)); + printf("%s\n", VSB_data(vsb)); + VSB_destroy(&vsb); +}