output: add more items to mustach tags

Base level printing; localstime, number of ranges and shared networks,
project version, and file paths and time stamps.

Also print error and stop template processing when unknown tag is
encountered.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2017-11-14 10:46:48 +00:00
parent d24313d25a
commit ff3d9523e6
No known key found for this signature in database
GPG key ID: A9553245FDE9B739
4 changed files with 154 additions and 34 deletions

View file

@ -14,7 +14,7 @@ Subnets:{{#subnets}}
backup_percent: {{backup_percent}} backup_percent: {{backup_percent}}
status: {{status}} status: {{status}}
gettimeofday: {{gettimeofday}} gettimeofday: {{gettimeofday}}
lease_file_mtime: {{lease_file_mtime}} lease_file_epoch_mtime: {{lease_file_epoch_mtime}}
{{/subnets}} {{/subnets}}
Shared-networks:{{#shared-networks}} Shared-networks:{{#shared-networks}}
@ -30,7 +30,7 @@ Shared-networks:{{#shared-networks}}
backup_percent: {{backup_percent}} backup_percent: {{backup_percent}}
status: {{status}} status: {{status}}
gettimeofday: {{gettimeofday}} gettimeofday: {{gettimeofday}}
lease_file_mtime: {{lease_file_mtime}} lease_file_epoch_mtime: {{lease_file_epoch_mtime}}
{{/shared-networks}} {{/shared-networks}}
Summary:{{#summary}} Summary:{{#summary}}
@ -46,5 +46,22 @@ Summary:{{#summary}}
backup_percent: {{backup_percent}} backup_percent: {{backup_percent}}
status: {{status}} status: {{status}}
gettimeofday: {{gettimeofday}} gettimeofday: {{gettimeofday}}
lease_file_mtime: {{lease_file_mtime}} lease_file_epoch_mtime: {{lease_file_epoch_mtime}}
{{/summary}} {{/summary}}
localtime: {{localtime}}
number_of_ranges: {{number_of_ranges}}
number_of_shared_networks: {{number_of_shared_networks}}
version: {{version}}
conf_file_path: {{conf_file_path}}
conf_file_local_mtime: {{conf_file_local_mtime}}
conf_file_epoch_mtime: {{conf_file_epoch_mtime}}
lease_file_path: {{lease_file_path}}
lease_file_local_mtime: {{lease_file_local_mtime}}
lease_file_epoch_mtime: {{lease_file_epoch_mtime}}
template_file_path: {{template_file_path}}
template_file_local_mtime: {{template_file_local_mtime}}
template_file_epoch_mtime: {{template_file_epoch_mtime}}

View file

@ -45,12 +45,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include "close-stream.h" #include "close-stream.h"
#include "dhcpd-pools.h" #include "dhcpd-pools.h"
#include "error.h" #include "error.h"
#include "mustach.h" #include "mustach.h"
#include "strftime.h"
#include "xalloc.h" #include "xalloc.h"
/*! \struct expl /*! \struct expl
@ -67,14 +69,109 @@ struct expl {
static int must_enter(void *closure, const char *name); static int must_enter(void *closure, const char *name);
static int must_leave(void *closure); static int must_leave(void *closure);
/*! \brief This function can be called when mustach template is invalid. static void dp_time_tool(FILE *file, const char *path, int epoch)
* In such case either must_put_range or must_put_shnet is tried to call before
* must_enter. */
static int must_put_err(void *closure __attribute__ ((unused)),
const char *name __attribute__ ((unused)),
int escape __attribute__ ((unused)), FILE *file __attribute__ ((unused)))
{ {
return MUSTACH_ERROR_SYSTEM; time_t t;
/* a file or now */
if (path) {
struct stat st;
stat(path, &st);
t = st.st_mtime;
} else
t = time(NULL);
/* epoc or iso time stamp */
if (epoch)
fprintf(file, "%ld", t);
else {
char time_stamp[64];
struct tm tm;
int len;
localtime_r(&t, &tm);
len = snprintf(time_stamp, sizeof(time_stamp), "%4d-%.2d-%.2dT%02d:%02d:%02d",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
strftime(time_stamp + len, sizeof(time_stamp) - len, "%z", &tm);
fprintf(file, "%s", time_stamp);
}
}
/*! \brief Template base level tag parser and printer. */
static int must_put_base(void *closure, const char *name, int escape
__attribute__ ((unused)), FILE *file)
{
struct expl *e = closure;
if (!strcmp(name, "localtime")) {
dp_time_tool(file, NULL, 0);
return 0;
}
if (!strcmp(name, "number_of_ranges")) {
fprintf(file, "%u", e->state->num_ranges);
return 0;
}
if (!strcmp(name, "number_of_shared_networks")) {
static uint32_t num = 0xffffffff;
if (num == 0xffffffff) {
/* Use of static num ensures this is done only once. */
struct shared_network_t *shared_p;
num = 0;
for (shared_p = e->state->shared_net_root->next; shared_p;
shared_p = shared_p->next)
num++;
}
fprintf(file, "%u", num);
return 0;
}
if (!strcmp(name, "version")) {
fprintf(file, "%s", PACKAGE_VERSION);
return 0;
}
/* lease file */
if (!strcmp(name, "lease_file_path")) {
fprintf(file, "%s", e->state->dhcpdlease_file);
return 0;
}
if (!strcmp(name, "lease_file_local_mtime")) {
dp_time_tool(file, e->state->dhcpdlease_file, 0);
return 0;
}
if (!strcmp(name, "lease_file_epoch_mtime")) {
dp_time_tool(file, e->state->dhcpdlease_file, 1);
return 0;
}
/* conf file */
if (!strcmp(name, "conf_file_path")) {
fprintf(file, "%s", e->state->dhcpdconf_file);
return 0;
}
if (!strcmp(name, "conf_file_local_mtime")) {
dp_time_tool(file, e->state->dhcpdconf_file, 0);
return 0;
}
if (!strcmp(name, "conf_file_epoch_mtime")) {
dp_time_tool(file, e->state->dhcpdconf_file, 1);
return 0;
}
/* template file */
if (!strcmp(name, "template_file_path")) {
fprintf(file, "%s", e->state->mustach_template);
return 0;
}
if (!strcmp(name, "template_file_local_mtime")) {
dp_time_tool(file, e->state->mustach_template, 0);
return 0;
}
if (!strcmp(name, "template_file_epoch_mtime")) {
dp_time_tool(file, e->state->mustach_template, 1);
return 0;
}
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
} }
/*! \struct mustach_itf /*! \struct mustach_itf
@ -82,7 +179,7 @@ static int must_put_err(void *closure __attribute__ ((unused)),
static struct mustach_itf itf = { static struct mustach_itf itf = {
.start = NULL, .start = NULL,
.enter = must_enter, .enter = must_enter,
.put = must_put_err, .put = must_put_base,
.next = NULL, .next = NULL,
.leave = must_leave .leave = must_leave
}; };
@ -153,20 +250,15 @@ static int must_put_range(void *closure, const char *name, int escape
return 0; return 0;
} }
if (!strcmp(name, "gettimeofday")) { if (!strcmp(name, "gettimeofday")) {
struct timeval tp; dp_time_tool(file, NULL, 1);
gettimeofday(&tp, NULL);
fprintf(file, "%ld", tp.tv_sec);
return 0; return 0;
} }
if (!strcmp(name, "lease_file_mtime")) { if (!strcmp(name, "lease_file_epoch_mtime")) {
struct stat st; dp_time_tool(file, e->state->dhcpdlease_file, 1);
stat(e->state->dhcpdlease_file, &st);
fprintf(file, "%ld", st.st_mtime);
return 0; return 0;
} }
return 0; error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
} }
/*! \brief Mustach shared networks aka {{#shared-networks}} tag parser and printer. */ /*! \brief Mustach shared networks aka {{#shared-networks}} tag parser and printer. */
@ -222,20 +314,15 @@ static int must_put_shnet(void *closure, const char *name, int escape
return 0; return 0;
} }
if (!strcmp(name, "gettimeofday")) { if (!strcmp(name, "gettimeofday")) {
struct timeval tp; dp_time_tool(file, NULL, 1);
gettimeofday(&tp, NULL);
fprintf(file, "%ld", tp.tv_sec);
return 0; return 0;
} }
if (!strcmp(name, "lease_file_mtime")) { if (!strcmp(name, "lease_file_epoch_mtime")) {
struct stat st; dp_time_tool(file, e->state->dhcpdlease_file, 1);
stat(e->state->dhcpdlease_file, &st);
fprintf(file, "%ld", st.st_mtime);
return 0; return 0;
} }
return 0; error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
} }
/*! \brief A function to move to next range when {{/subnets}} is encountered. */ /*! \brief A function to move to next range when {{/subnets}} is encountered. */
@ -302,7 +389,8 @@ static int must_enter(void *closure, const char *name)
shnet_output_helper(e->state, &e->oh, e->shnet_p); shnet_output_helper(e->state, &e->oh, e->shnet_p);
return 1; return 1;
} }
return 0; error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
} }
/*! \brief Function that is called when all elements within a print loop are outputed. */ /*! \brief Function that is called when all elements within a print loop are outputed. */
@ -312,6 +400,7 @@ static int must_leave(void *closure)
e->shnet_p = e->state->shared_net_root; e->shnet_p = e->state->shared_net_root;
e->range_p = e->state->ranges; e->range_p = e->state->ranges;
itf.put = must_put_base;
return 0; return 0;
} }

View file

@ -114,6 +114,12 @@ Summary:
backup_percent: 2 backup_percent: 2
status: 0 status: 0
number_of_ranges: 5
number_of_shared_networks: 2
--- skip ok --- --- skip ok ---
Subnets: Subnets:
location: example1 location: example1
@ -189,3 +195,9 @@ Summary:
backup_percent: 2 backup_percent: 2
status: 0 status: 0
number_of_ranges: 5
number_of_shared_networks: 2

View file

@ -8,14 +8,16 @@ if [ ! -d tests/outputs ]; then
mkdir tests/outputs mkdir tests/outputs
fi fi
remove='/gettimeofday:/d; /^localtime:/d; /^conf_file_/d; /lease_file_/d; /^template_file_/d; /^version:/d'
dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \ dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \
--mustach $top_srcdir/samples/mustach.template | --mustach $top_srcdir/samples/mustach.template |
sed '/gettimeofday:/d; /lease_file_mtime:/d' >| tests/outputs/$IAM sed "$remove" >| tests/outputs/$IAM
echo "--- skip ok ---" >> tests/outputs/$IAM echo "--- skip ok ---" >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \ dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \
--mustach $top_srcdir/samples/mustach.template --skip=ok --warning 44 | --mustach $top_srcdir/samples/mustach.template --skip=ok --warning 44 |
sed '/gettimeofday:/d; /lease_file_mtime:/d' >> tests/outputs/$IAM sed "$remove" >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $? exit $?