Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Varnishadm: Add -e argument #4018

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
131 changes: 72 additions & 59 deletions bin/varnishadm/varnishadm.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
#include "vapi/vsig.h"
#include "vapi/vsm.h"
#include "vas.h"
#include "vcli.h"
#include "vcli_serve.h"
#include "vsb.h"
#include "vjsn.h"
#include "vtcp.h"

Expand All @@ -83,8 +84,14 @@ enum pass_mode_e {

static double timeout = 5;
static int p_arg = 0;
static int e_arg = 0;
static int line_sock;

static void v_noreturn_
adm_exit(enum VCLI_status_e status) {
RL_EXIT(status / 100);
}

static void
cli_write(int sock, const char *s)
{
Expand All @@ -95,7 +102,7 @@ cli_write(int sock, const char *s)
if (i == l)
return;
perror("Write error CLI socket");
RL_EXIT(1);
adm_exit(CLIS_COMMS);
}

/*
Expand Down Expand Up @@ -166,6 +173,24 @@ cli_sock(const char *T_arg, const char *S_arg)
return (sock);
}

static void
pass_print_answer(int status, char *answer, enum pass_mode_e mode)
{
if (p_arg && answer != NULL) {
printf("%-3u %-8zu\n%s", status, strlen(answer), answer);
} else if (p_arg) {
printf("%-3u %-8u\n", status, 0U);
} else {
if (mode == pass_interactive)
printf("%u\n", status);
if (answer != NULL)
printf("%s\n", answer);
if (status == CLIS_TRUNCATED)
printf("[response was truncated]\n");
}
fflush(stdout);
}

static unsigned
pass_answer(int fd, enum pass_mode_e mode)
{
Expand All @@ -176,27 +201,15 @@ pass_answer(int fd, enum pass_mode_e mode)
if (u) {
if (status == CLIS_COMMS) {
fprintf(stderr, "%s\n", answer);
RL_EXIT(2);
adm_exit(CLIS_COMMS);
}
if (answer)
fprintf(stderr, "%s\n", answer);
RL_EXIT(1);
adm_exit(status);
}

if (p_arg && answer != NULL) {
printf("%-3u %-8zu\n%s", status, strlen(answer), answer);
} else if (p_arg) {
printf("%-3u %-8u\n", status, 0U);
} else {
if (mode == pass_interactive)
printf("%u\n", status);
if (answer != NULL)
printf("%s\n", answer);
if (status == CLIS_TRUNCATED)
printf("[response was truncated]\n");
}
pass_print_answer(status, answer, mode);
free(answer);
(void)fflush(stdout);
return (status);
}

Expand All @@ -219,7 +232,7 @@ do_args(int sock, int argc, char * const *argv)
exit(0);
if (!p_arg)
fprintf(stderr, "Command failed with error code %u\n", status);
exit(1);
adm_exit(status);
}

/* Callback for readline, doesn't take a private pointer, so we need
Expand Down Expand Up @@ -338,57 +351,54 @@ interactive(int sock)
}
}

/*--------------------------------------------------------------------*/

static void
vadm_cli_cb_after(const struct cli *cli)
{
const char *cmd;

if (!e_arg)
return;

if (cli->result == CLIS_OK || cli->result == CLIS_TRUNCATED)
return;

cmd = VSB_data(cli->cmd);
if (*cmd == '-')
return;

pass_print_answer(cli->result, VSB_data(cli->sb), pass_script);
fprintf(stderr, "\nCommand \"%s\" failed with error code %u\n",
cmd, cli->result);
adm_exit(cli->result);
}

/*
* No arguments given, simply pass bytes on stdin/stdout and CLI socket
*/

static void v_noreturn_
pass(int sock)
{
struct pollfd fds[2];
char buf[1024];
struct VCLP *vclp;
int i;
ssize_t n;
int busy = 0;

fds[0].fd = sock;
fds[0].events = POLLIN;
fds[1].fd = 0;
fds[1].events = POLLIN;
while (1) {
i = poll(fds, 2, -1);
if (i == -1 && errno == EINTR) {
continue;
}
assert(i > 0);
if (fds[0].revents & POLLIN) {
(void)pass_answer(fds[0].fd, pass_script);
busy = 0;
if (fds[1].fd < 0)
RL_EXIT(0);
}
if (fds[1].revents & POLLIN || fds[1].revents & POLLHUP) {
n = read(fds[1].fd, buf, sizeof buf - 1);
if (n == 0) {
if (!busy)
RL_EXIT(0);
fds[1].fd = -1;
} else if (n < 0) {
RL_EXIT(0);
} else {
busy = 1;
buf[n] = '\0';
cli_write(sock, buf);
}
}
}
vclp = VCLP_New(STDIN_FILENO, STDOUT_FILENO,
sock, p_arg ? PROTO_FULL : PROTO_HEADLESS, timeout);
AN(vclp);
VCLP_SetHooks(vclp, NULL, vadm_cli_cb_after);
do {
i = VCLP_Poll(vclp, -1);
} while (i == 0);
RL_EXIT(0);
}


static void v_noreturn_
usage(int status)
{
fprintf(stderr,
"Usage: varnishadm [-h] [-n ident] [-p] [-S secretfile] "
"Usage: varnishadm [-e] [-h] [-n ident] [-p] [-S secretfile] "
"[-T [address]:port] [-t timeout] [command [...]]\n");
fprintf(stderr, "\t-n is mutually exclusive with -S and -T\n");
exit(status);
Expand Down Expand Up @@ -452,7 +462,7 @@ t_arg_timeout(const char *t_arg)
return (1);
}

#define OPTARG "hn:pS:T:t:"
#define OPTARG "ehn:pS:T:t:"

int
main(int argc, char * const *argv)
Expand All @@ -477,6 +487,9 @@ main(int argc, char * const *argv)
*/
while ((opt = getopt(argc, argv, "+" OPTARG)) != -1) {
switch (opt) {
case 'e':
e_arg = 1;
break;
case 'h':
/* Usage help */
usage(0);
Expand All @@ -496,7 +509,7 @@ main(int argc, char * const *argv)
t_arg = optarg;
break;
default:
usage(1);
usage(2);
}
}

Expand All @@ -505,11 +518,11 @@ main(int argc, char * const *argv)

if (T_arg != NULL) {
if (n_arg != NULL)
usage(1);
usage(2);
sock = cli_sock(T_arg, S_arg);
} else {
if (S_arg != NULL)
usage(1);
usage(2);
sock = n_arg_sock(n_arg, t_arg);
}
if (sock < 0)
Expand Down
2 changes: 1 addition & 1 deletion bin/varnishd/mgt/mgt_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ mcf_askchild(struct cli *cli, const char * const *av, void *priv)
}
VSB_clear(cli_buf);
for (i = 1; av[i] != NULL; i++) {
VSB_quote(cli_buf, av[i], strlen(av[i]), 0);
VSB_quote(cli_buf, av[i], strlen(av[i]), VSB_QUOTE_CLI);
VSB_putc(cli_buf, ' ');
}
VSB_putc(cli_buf, '\n');
Expand Down
2 changes: 1 addition & 1 deletion bin/varnishtest/tests/m00000.vtc
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ shell {

varnish v1 -clierr 300 "vcl.load f1 ${tmpdir}/f1"

shell -exit 1 -expect {failing as requested} {
shell -exit 3 -expect {failing as requested} {
varnishadm -t 10 -n ${tmpdir}/v1 vcl.load f1 ${tmpdir}/f1
}

Expand Down
2 changes: 1 addition & 1 deletion bin/varnishtest/tests/u00000.vtc
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ shell {varnishadm -n ${tmpdir}/v1 start}

shell {varnishadm -n ${tmpdir}/v1 debug.listen_address}

shell -exit 1 -expect "Command failed with error code 500" {
shell -exit 5 -expect "Command failed with error code 500" {
varnishadm -n ${tmpdir}/v1 quit
}

Expand Down
69 changes: 68 additions & 1 deletion bin/varnishtest/tests/u00001.vtc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ shell {
# same command via stdin
shell {
echo status | varnishadm -n ${v1_name} -p | tr ' ' _ >actual.txt
printf '\n' >>actual.txt
diff -u expected.txt actual.txt
}

Expand All @@ -61,3 +60,71 @@ shell -err {
varnishadm -n ${v1_name} -p |
python3 -c 'import sys, json; print(json.load(sys.stdin))'
}

shell {
cat > cli_file.txt <<-EOF
status
foo
vcl.list
EOF
}

shell {
cat > expected_success.txt <<-EOF
Child in state running
Unknown request.
Type 'help' for more info.

active auto warm 0 vcl1

EOF
}

shell {
cat > expected_abort.txt <<-EOF
Child in state running
Unknown request.
Type 'help' for more info.

EOF
}

shell { varnishadm -n ${v1_name} < cli_file.txt }
shell { varnishadm -n ${v1_name} < cli_file.txt | diff -u expected_success.txt - }

shell -exit 1 { varnishadm -e -n ${v1_name} < cli_file.txt }
shell { varnishadm -e -n ${v1_name} < cli_file.txt | diff -u expected_abort.txt - }

shell { cat cli_file.txt | varnishadm -n ${v1_name} }
shell { cat cli_file.txt | varnishadm -n ${v1_name} | diff -u expected_success.txt - }

shell -exit 1 { cat cli_file.txt | varnishadm -e -n ${v1_name} }
shell { cat cli_file.txt | varnishadm -e -n ${v1_name} | diff -u expected_abort.txt - }

shell {
cat > cli_file.txt <<-EOF
status
-foo
vcl.list
EOF
}

shell { varnishadm -e -n ${v1_name} < cli_file.txt }
shell { varnishadm -e -n ${v1_name} < cli_file.txt | diff -u expected_success.txt - }

shell { cat cli_file.txt | varnishadm -e -n ${v1_name} }
shell { cat cli_file.txt | varnishadm -e -n ${v1_name} | diff -u expected_success.txt - }

shell {
cat > cli_heredoc.txt <<-EOF1
vcl.inline bar << EOF2
vcl 4.1;

backend default none;
EOF2
EOF1
}

shell { varnishadm -e -p -n ${v1_name} < cli_heredoc.txt }
shell { varnishadm -n ${v1_name} vcl.discard bar }
shell { cat cli_heredoc.txt | varnishadm -e -p -n ${v1_name} }
2 changes: 1 addition & 1 deletion bin/varnishtest/tests/u00012.vtc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ process p1 -screen_dump -write "\x04" -wait
process p1 -log {varnishadm -t foobar 2>&1} -expect-exit 2 -run
process p1 -expect-text 0 0 "-t: Invalid argument:"

process p1 -log {varnishadm -Q 2>&1} -expect-exit 1 -run
process p1 -log {varnishadm -Q 2>&1} -expect-exit 2 -run
process p1 -expect-text 0 0 "Usage: varnishadm"

process p2 -log {varnishadm -h 2>&1} -expect-exit 0 -run
Expand Down
18 changes: 16 additions & 2 deletions doc/sphinx/reference/varnishadm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Control a running Varnish instance
SYNOPSIS
========

varnishadm [-h] [-n ident] [-p] [-S secretfile] [-T [address]:port] [-t timeout] [command [...]]
varnishadm [-e] [-h] [-n ident] [-p] [-S secretfile] [-T [address]:port] [-t timeout] [command [...]]


DESCRIPTION
Expand All @@ -40,6 +40,14 @@ replies between the CLI socket and stdin/stdout.
OPTIONS
=======

-e
Exit immediately if a command fails in `pass` mode with an exit
status indicating the nature of the error (See EXIT STATUS for details).
This has no effect on `interactive` mode (except when `-p` is used).
Similarly to `CLI Command File` (see :ref:`varnishd(1)`), if a command
is prefixed with '-', its failure will be ignored and will not cause
varnishadm to exit.

-h
Print program usage and exit.

Expand Down Expand Up @@ -75,7 +83,13 @@ EXIT STATUS
===========

If a command is given, the exit status of the `varnishadm` utility is
zero if the command succeeded, and non-zero otherwise.
zero if the command succeeded, and one of the following otherwise:

1: could not execute the command
2: bad usage
3: the command failed
4: the connection was lost
5: the CLI session was terminated

EXAMPLES
========
Expand Down
Loading