commit af490b2c935de6beea6095b770c38ce7bde92a8e from: Stefan Sperling date: Mon Jun 23 10:01:38 2025 UTC add gotsys apply -w option which waits until sysconf has been run commit - bd2d269200403f8168de26b8229d7c30de792d3b commit + af490b2c935de6beea6095b770c38ce7bde92a8e blob - 00820a53c513998384af2849c1311c660ceeef6f blob + d3405c5db2e7a48954a166f23e2cb17daa59a9bf --- gotsys/gotsys.1 +++ gotsys/gotsys.1 @@ -47,7 +47,7 @@ The commands for .Nm are as follows: .Bl -tag -width Ds -.It Cm apply Oo Fl c Ar commit Oc Oo Fl f Ar socket Oc Oo Fl r Ar repository-path Oc Oo Ar file Oc +.It Cm apply Oo Fl c Ar commit Oc Oo Fl f Ar socket Oc Oo Fl r Ar repository-path Oc Oo Fl w Oc Oo Ar file Oc Trigger system configuration tasks based on the .Xr gotsys.conf 5 configuration @@ -119,6 +119,10 @@ Use the repository at the specified path. If not specified, the repository path .Pa /git/gotsys.git will be used. +.It Fl w +Wait until +.Xr gotsysd 8 +is done trying to apply the configuration and report the result. .El .It Cm check Oo Fl q Oc Oo Fl f Ar file Oc Read a blob - ba69385c1f238933082336acee61d9a579768e9e blob + 584ac4aa540ecb67f99cf1c3451ceab525de382e --- gotsys/gotsys.c +++ gotsys/gotsys.c @@ -164,7 +164,7 @@ __dead static void usage_apply(void) { fprintf(stderr, "usage: %s apply [-f socket] [-r repository] " - "[-c commit] [filename]", getprogname()); + "[-c commit] [-w] [filename]", getprogname()); exit(1); } @@ -230,7 +230,7 @@ cmd_apply(int argc, char *argv[]) const char *filename = GOTSYSD_SYSCONF_FILENAME; const char *socket_path = GOTSYSD_UNIX_SOCKET; struct got_commit_object *commit = NULL; - int ch, ret, fd = -1, sysconf_fd = -1, gotsysd_sock = -1; + int ch, ret, fd = -1, sysconf_fd = -1, gotsysd_sock = -1, wait = 0; FILE *sysconf_file = NULL; struct got_object_id *commit_id = NULL; struct gotsysd_imsg_cmd_sysconf sysconf_cmd; @@ -239,7 +239,7 @@ cmd_apply(int argc, char *argv[]) memset(&ibuf, 0, sizeof(ibuf)); - while ((ch = getopt(argc, argv, "f:c:r:")) != -1) { + while ((ch = getopt(argc, argv, "f:c:r:w")) != -1) { switch (ch) { case 'c': commit_id_str = optarg; @@ -256,6 +256,9 @@ cmd_apply(int argc, char *argv[]) } got_path_strip_trailing_slashes(repo_path); break; + case 'w': + wait = 1; + break; default: usage_apply(); /* NOTREACHED */ @@ -369,38 +372,48 @@ cmd_apply(int argc, char *argv[]) goto done; } #endif - n = imsgbuf_read(&ibuf); - if (n == -1) { - err = got_error_from_errno("imsgbuf_read"); - goto done; - } - if (n == 0) { - err = got_error(GOT_ERR_EOF); - goto done; - } + do { + n = imsgbuf_read(&ibuf); + if (n == -1) { + err = got_error_from_errno("imsgbuf_read"); + goto done; + } + if (n == 0) { + err = got_error(GOT_ERR_EOF); + goto done; + } - n = imsg_get(&ibuf, &imsg); - if (n == -1) { - err = got_error_from_errno("imsg_get"); - goto done; - } - if (n == 0) { - err = got_error(GOT_ERR_PRIVSEP_READ); - goto done; - } + n = imsg_get(&ibuf, &imsg); + if (n == -1) { + err = got_error_from_errno("imsg_get"); + goto done; + } + if (n == 0) { + err = got_error(GOT_ERR_PRIVSEP_READ); + goto done; + } - switch (imsg.hdr.type) { - case GOTSYSD_IMSG_ERROR: - err = recv_error(&imsg); - break; - case GOTSYSD_IMSG_SYSCONF_STARTED: - break; - default: - err = got_error(GOT_ERR_PRIVSEP_MSG); - break; - } + switch (imsg.hdr.type) { + case GOTSYSD_IMSG_ERROR: + err = recv_error(&imsg); + break; + case GOTSYSD_IMSG_SYSCONF_STARTED: + break; + case GOTSYSD_IMSG_SYSCONF_SUCCESS: + printf("sysconf success\n"); + wait = 0; + break; + case GOTSYSD_IMSG_SYSCONF_FAILURE: + err = got_error_fmt(GOT_ERR_ON_SERVER_SIDE, + "sysconf failure"); + break; + default: + err = got_error(GOT_ERR_PRIVSEP_MSG); + break; + } - imsg_free(&imsg); + imsg_free(&imsg); + } while (err == NULL && wait); done: imsgbuf_clear(&ibuf); free(repo_path); blob - e82a68f6c011d5ed50ce21ff9ea6ea50c3beb9e6 blob + 8628a270bcaa8929d1e004abd3806a8d7a407f26 --- gotsysd/gotsysd.c +++ gotsysd/gotsysd.c @@ -62,6 +62,7 @@ struct gotsysd_child_proc { int pipe[2]; struct gotsysd_imsgev iev; struct event tmo; + uint32_t client_id; TAILQ_ENTRY(gotsysd_child_proc) entry; }; @@ -70,6 +71,7 @@ static TAILQ_HEAD(gotsysd_procs, gotsysd_child_proc) p enum gotsysd_client_state { GOTSYSD_CLIENT_STATE_NEW = -1, GOTSYSD_CLIENT_STATE_ACCESS_GRANTED = 1, + GOTSYSD_CLIENT_STATE_SYSCONF_STARTED, }; struct gotsysd_client { @@ -260,6 +262,29 @@ find_client(uint32_t client_id) } static void +client_sysconf_done(uint32_t client_id, int exit_status) +{ + struct gotsysd_client *client; + int imsg_code; + + client = find_client(client_id); + if (client == NULL) + return; + + if (client->state != GOTSYSD_CLIENT_STATE_SYSCONF_STARTED) + return; + + if (exit_status == 0) + imsg_code = GOTSYSD_IMSG_SYSCONF_SUCCESS; + else + imsg_code = GOTSYSD_IMSG_SYSCONF_FAILURE; + + if (gotsysd_imsg_compose_event(&client->iev, imsg_code, + GOTSYSD_PROC_GOTSYSD, -1, NULL, 0) == -1) + log_warn("imsg compose %d", imsg_code); +} + +static void disconnect(struct gotsysd_client *client) { struct gotsysd_imsg_disconnect idisconnect; @@ -535,7 +560,8 @@ done: } static const struct got_error * -start_sysconf_child(int sysconf_fd, struct got_object_id *commit_id) +start_sysconf_child(int sysconf_fd, struct got_object_id *commit_id, + uint32_t client_id) { const struct got_error *err = NULL; struct gotsysd_child_proc *proc; @@ -556,6 +582,7 @@ start_sysconf_child(int sysconf_fd, struct got_object_ evtimer_set(&proc->tmo, kill_proc_timeout, proc); proc->type = GOTSYSD_PROC_SYSCONF; + proc->client_id = client_id; log_debug("running system configuration tasks for gotsys.conf from " "gotsys.git commit %s", commit_id_str); @@ -607,7 +634,7 @@ sysconf_cmd_timeout(int fd, short ev, void *d) STAILQ_REMOVE_HEAD(&gotsysd.sysconf_pending, entry); - err = start_sysconf_child(cmd->fd, &cmd->commit_id); + err = start_sysconf_child(cmd->fd, &cmd->commit_id, cmd->client_id); if (err) { log_warn("could not start sysconf child process: %s", err->msg); @@ -650,7 +677,8 @@ run_sysconf(struct gotsysd_client *client, struct imsg return got_error(GOT_ERR_PRIVSEP_MSG); if (gotsysd.sysconf_proc == NULL) { - err = start_sysconf_child(sysconf_fd, &sysconf_cmd.commit_id); + err = start_sysconf_child(sysconf_fd, &sysconf_cmd.commit_id, + client->id); if (err) { close(sysconf_fd); return err; @@ -672,6 +700,7 @@ run_sysconf(struct gotsysd_client *client, struct imsg cmd->fd = sysconf_fd; memcpy(&cmd->commit_id, &sysconf_cmd.commit_id, sizeof(cmd->commit_id)); + cmd->client_id = client->id; STAILQ_INSERT_TAIL(&gotsysd.sysconf_pending, cmd, entry); evtimer_add(&gotsysd.sysconf_tmo, &tv); } @@ -681,7 +710,8 @@ run_sysconf(struct gotsysd_client *client, struct imsg GOTSYSD_IMSG_SYSCONF_STARTED, GOTSYSD_PROC_GOTSYSD, -1, NULL, 0) == -1) { err = got_error_from_errno("imsg compose SYSCONF_STARTED"); - } + } else + client->state = GOTSYSD_CLIENT_STATE_SYSCONF_STARTED; return NULL; } @@ -1565,6 +1595,11 @@ gotsysd_sighdlr(int sig, short event, void *arg) " signal %d", pid, WTERMSIG(status)); } + if (proc->type == GOTSYSD_PROC_SYSCONF) { + client_sysconf_done(proc->client_id, + WEXITSTATUS(status)); + } + if (proc == gotsysd.sysconf_proc) { gotsysd.sysconf_proc = NULL; if (gotsysd.sysconf_fd != -1) { blob - 6d37103e663e08e88c395b8e01b66320b5c4bc2f blob + f72e5f0ff065e99ca9f7e168dbd69ae18ba02940 --- gotsysd/gotsysd.h +++ gotsysd/gotsysd.h @@ -91,6 +91,7 @@ struct gotsysd_pending_sysconf_cmd { STAILQ_ENTRY(gotsysd_pending_sysconf_cmd) entry; int fd; struct got_object_id commit_id; + uint32_t client_id; }; STAILQ_HEAD(gotsysd_pending_sysconf_cmd_list, gotsysd_pending_sysconf_cmd); @@ -140,11 +141,12 @@ enum gotsysd_imsg_type { GOTSYSD_IMSG_INFO, GOTSYSD_IMSG_CMD_SYSCONF, GOTSYSD_IMSG_SYSCONF_STARTED, + GOTSYSD_IMSG_SYSCONF_SUCCESS, + GOTSYSD_IMSG_SYSCONF_FAILURE, /* Internal sysconf messages. */ GOTSYSD_IMSG_SYSCONF_READY, GOTSYSD_IMSG_SYSCONF_FD, - GOTSYSD_IMSG_SYSCONF_SUCCESS, /* Child processes management. */ GOTSYSD_IMSG_CONNECT_PROC, blob - 870e76a6fec7cb1fd96cdd2f47457c6ab86988d8 blob + d9cb7ba02a04c7708ffd8b434a1ff6d2b567e681 --- include/got_error.h +++ include/got_error.h @@ -196,6 +196,7 @@ #define GOT_ERR_GROUP_EXISTS 179 #define GOT_ERR_AUTHORIZED_KEY 180 #define GOT_ERR_CONNECTION_LIMIT 190 +#define GOT_ERR_ON_SERVER_SIDE 191 struct got_error { int code; blob - 922cdad6e22538c24d67ad78bf152e9edef33f49 blob + 8140daf14f5dd531f79f071964fa9ecc20349c17 --- lib/error.c +++ lib/error.c @@ -247,6 +247,7 @@ static const struct got_error got_errors[] = { { GOT_ERR_GROUP_EXISTS, "group already exists" }, { GOT_ERR_AUTHORIZED_KEY, "no authorized key found" }, { GOT_ERR_CONNECTION_LIMIT, "connection limit exceeded" }, + { GOT_ERR_ON_SERVER_SIDE, "see server-side logs for error details" }, }; static struct got_custom_error {