Mercurial > sci
diff scictl/scictl.c @ 22:dd078aea5d02
misc: use project/worker name as primary key
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 21 Jul 2022 20:23:22 +0200 |
parents | de4bf839b565 |
children | 2cb228f23f53 |
line wrap: on
line diff
--- a/scictl/scictl.c Tue Jul 19 22:45:44 2022 +0200 +++ b/scictl/scictl.c Thu Jul 21 20:23:22 2022 +0200 @@ -16,64 +16,81 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <err.h> +#include <limits.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdnoreturn.h> #include <unistd.h> +#include "apic.h" #include "config.h" -#include "req.h" #include "types.h" #include "util.h" -noreturn static void +static void usage(void) { - fprintf(stderr, "usage: %s [-s sock] command [args...]\n", getprogname()); + fprintf(stderr, "usage: %s [-u baseurl] command [args...]\n", getprogname()); exit(1); } -noreturn static void +static void help(void) { - fprintf(stderr, "usage: %s job-add project tag\n", getprogname()); - fprintf(stderr, " %s job-todo worker\n", getprogname()); - fprintf(stderr, " %s jobresult-add id worker exitcode console\n", getprogname()); - fprintf(stderr, " %s project-add name desc url script\n", getprogname()); - fprintf(stderr, " %s project-info name\n", getprogname()); - fprintf(stderr, " %s project-list\n", getprogname()); - fprintf(stderr, " %s project-update name key value\n", getprogname()); - fprintf(stderr, " %s worker-add name desc\n", getprogname()); - fprintf(stderr, " %s worker-list\n", getprogname()); + fprintf(stderr, "usage: scictl job-add project tag\n"); + fprintf(stderr, " scictl job-todo worker\n"); + fprintf(stderr, " scictl jobresult-add id worker exitcode console\n"); + fprintf(stderr, " scictl project-add name desc url script\n"); + fprintf(stderr, " scictl project-info name\n"); + fprintf(stderr, " scictl project-list\n"); + fprintf(stderr, " scictl project-update name key value\n"); + fprintf(stderr, " scictl worker-add name desc\n"); + fprintf(stderr, " scictl worker-list\n"); exit(0); } +static inline void +replace(char **str, const char *new) +{ + free(*str); + *str = util_strdup(new); +} + +long long +toint(const char *s) +{ + long long v; + const char *err; + + v = util_strtonum(s, 0, LLONG_MAX, &err); + + if (err) + util_die("abort: %s\n", err); + + return v; +} + static char * readfile(const char *path) { FILE *fp, *str; - char buf[BUFSIZ], *console; - size_t nr; + char buf[BUFSIZ], *console = NULL; + size_t nr, consolesz = 0; if (strcmp(path, "-") == 0) fp = stdin; else if (!(fp = fopen(path, "r"))) - err(1, "%s", path); + util_die("abort: %s: %s\n", path, strerror(errno)); - console = util_calloc(1, SCI_MSG_MAX); - - if (!(str = fmemopen(console, SCI_MSG_MAX, "w"))) - err(1, "fmemopen"); + if (!(str = open_memstream(&console, &consolesz))) + util_die("abort: open_memstream: %s\n", strerror(errno)); while ((nr = fread(buf, 1, sizeof (buf), fp)) > 0) fwrite(buf, 1, nr, str); - if ((ferror(fp) && !feof(fp)) || (ferror(str) && !feof(str))) { - free(console); - console = NULL; - } + if ((ferror(fp) && !feof(fp)) || (ferror(str) && !feof(str))) + util_die("abort: %s\n", strerror(errno)); fclose(str); fclose(fp); @@ -87,285 +104,218 @@ return fwrite(s, w, n, data); } -static json_t * -parse(const char *data) -{ - json_t *doc; - json_error_t err; - - if (!(json_loads(doc, 0, &err))) - die("abort: unable to parse JSON: %s\n", err.text); - - return doc; -} - -static json_t * -get(const char *url) -{ - CURL *curl; - CURLcode code; - FILE *fp; - char buf[HTTP_BUF_MAX]; - long ret; - - if (!(fp = fmemopen(buf, sizeof (buf), "w"))) - die("abort: %s", strerror(errno)); - - curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, extract); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3L); - code = curl_easy_perform(curl); - - if (code != CURLE_OK) - die("abort: %s", curl_easy_strerror(code)); - - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &ret); - - if (ret != 200) - die("abort: HTTP %ld\n", ret); - - curl_easy_cleanup(curl); - fclose(fp); - - return parse(buf); -} - -static struct req +static void cmd_job_add(int argc, char **argv) { struct job job = {0}; - struct project project = {0}; + struct apic req; + + if (argc < 3) + usage(); + + job.project_name = util_strdup(argv[1]); + job.tag = util_strdup(argv[2]); + + if (apic_job_add(&req, &job) < 0) + util_die("abort: %s\n", req.error); + + apic_finish(&req); + job_finish(&job); +} + +static void +cmd_job_todo(int argc, char **argv) +{ + struct job jobs[SCI_JOB_LIST_MAX] = {0}; + size_t jobsz; + struct apic req; if (argc < 2) usage(); - project.name = argv[0]; - - if (_project_find(&project, argv[0])).status) - return rp; - - job.project_id = project.id; - job.tag = argv[1]; - - rj = req_job_add(&job); - req_finish(&rp); - - return rj; -} - -static struct req -cmd_job_todo(int argc, char **argv) -{ - struct project projects[SCI_PROJECT_MAX] = {0}; - struct job jobs[SCI_JOB_LIST_MAX] = {0}; - struct req rp, rj; - size_t projectsz = UTIL_SIZE(projects), jobsz = UTIL_SIZE(jobs); - - if (argc < 1) - usage(); - - /* First retrieve projects for a better listing. */ - if ((rp = req_project_list(projects, &projectsz)).status) - return rp; - - if ((rj = req_job_todo(jobs, &jobsz, argv[0])).status) { - req_finish(&rp); - return rj; - } + if ((jobsz = apic_job_todo(&req, jobs, UTIL_SIZE(jobs), toint(argv[1])))) + util_die("abort: %s\n", req.error); for (size_t i = 0; i < jobsz; ++i) { - const char *project = "unknown"; - - /* Find project if exists (it should). */ - for (size_t p = 0; p < projectsz; ++p) { - if (projects[p].id == jobs[i].project_id) { - project = projects[p].name; - break; - } - } - - printf("%-16s%d\n", "id:", jobs[i].id); + printf("%-16s%jd\n", "id:", jobs[i].id); printf("%-16s%s\n", "tag:", jobs[i].tag); - printf("%-16s%s\n", "project:", project); + printf("%-16s%s\n", "project:", jobs[i].project_name); if (i + 1 < jobsz) printf("\n"); + + job_finish(&jobs[i]); } - req_finish(&rp); - - return rj; + apic_finish(&req); } -static struct req +static void cmd_jobresult_add(int argc, char **argv) { struct jobresult res = {0}; - struct worker wk = {0}; - struct req rw, rj; - char *log; + struct apic req; + + if (argc < 5) + usage(); + + res.job_id = toint(argv[1]); + res.worker_name = util_strdup(argv[2]); + res.exitcode = toint(argv[3]); + res.log = readfile(argv[4]); + + if (apic_jobresult_add(&req, &res) < 0) + util_die("abort: unable to add job result: %s\n", req.error); + + apic_finish(&req); + jobresult_finish(&res); +} + +static void +cmd_project_add(int argc, char **argv) +{ + struct project pc = {0}; + struct apic req; if (argc < 5) usage(); - /* Find worker id. */ - if ((rw = req_worker_find(&wk, argv[1])).status) - return rw; + pc.name = util_strdup(argv[1]); + pc.desc = util_strdup(argv[2]); + pc.url = util_strdup(argv[3]); + pc.script = readfile(argv[4]); - res.job_id = strtoll(argv[0], NULL, 10); - res.exitcode = strtoll(argv[2], NULL, 10); - res.worker_id = wk.id; - res.log = log = readfile(argv[3]); - rj = req_jobresult_add(&res); + if (apic_project_save(&req, &pc) < 0) + util_die("abort: unable to create project: %s\n", req.error); - free(log); - req_finish(&rw); - - return rj; + apic_finish(&req); + project_finish(&pc); } -static struct req -cmd_project_add(int argc, char **argv) +static void +cmd_project_update(int argc, char **argv) { - struct project pc = {0}; - struct req res; - char *script; + struct project pc; + struct apic req; if (argc < 4) usage(); - pc.name = argv[0]; - pc.desc = argv[1]; - pc.url = argv[2]; - pc.script = script = readfile(argv[3]); - res = req_project_add(&pc); + if (apic_project_find(&req, &pc, argv[1]) < 0) + util_die("abort: unable to find project: %s\n", req.error); - free(script); + if (strcmp(argv[2], "name") == 0) + replace(&pc.name, argv[3]); + else if (strcmp(argv[2], "desc") == 0) + replace(&pc.desc, argv[3]); + else if (strcmp(argv[2], "url") == 0) + replace(&pc.url, argv[3]); + else if (strcmp(argv[2], "script") == 0) + replace(&pc.script, readfile(argv[3])); - return res; + if (apic_project_save(&req, &pc) < 0) + util_die("abort: unable to save project: %s\n", req.error); + + apic_finish(&req); + project_finish(&pc); } -static struct req -cmd_project_update(int argc, char **argv) -{ - struct project pc; - struct req rget, rsend; - char *script = NULL; - - if (argc < 3) - help(); - - if ((rget = req_project_find(&pc, argv[0])).status) - return rget; - - if (strcmp(argv[1], "name") == 0) - pc.name = argv[2]; - else if (strcmp(argv[1], "desc") == 0) - pc.desc = argv[2]; - else if (strcmp(argv[1], "url") == 0) - pc.url = argv[2]; - else if (strcmp(argv[1], "script") == 0) - pc.script = script = readfile(argv[2]); - - rsend = req_project_update(&pc); - - req_finish(&rget); - free(script); - - return rsend; -} - -static struct req +static void cmd_project_info(int argc, char **argv) { struct project project = {0}; - struct req req; + struct apic req; - if (argc < 1) + if (argc < 2) usage(); - if ((req = req_project_find(&project, argv[0])).status) - return req; + if (apic_project_find(&req, &project, argv[1]) < 0) + util_die("abort: unable to find project: %s\n", req.error); - printf("%-16s%d\n", "id:", project.id); printf("%-16s%s\n", "name:", project.name); printf("%-16s%s\n", "desc:", project.desc); printf("%-16s%s\n", "url:", project.url); printf("\n"); printf("%s", project.script); - return req; + apic_finish(&req); + project_finish(&project); } -static struct req +static void cmd_project_list(int argc, char **argv) { (void)argc; (void)argv; struct project projects[SCI_PROJECT_MAX] = {0}; - struct req req; - size_t projectsz = UTIL_SIZE(projects); + struct apic req; + ssize_t projectsz; - if ((req = req_project_list(projects, &projectsz)).status) - return req; + if ((projectsz = apic_project_list(&req, projects, UTIL_SIZE(projects))) < 0) + util_die("abort: unable to list projects: %s\n", req.error); for (size_t i = 0; i < projectsz; ++i) { - printf("%-16s%d\n", "id:", projects[i].id); printf("%-16s%s\n", "name:", projects[i].name); printf("%-16s%s\n", "desc:", projects[i].desc); printf("%-16s%s\n", "url:", projects[i].url); if (i + 1 < projectsz) printf("\n"); + + project_finish(&projects[i]); } - return req; + apic_finish(&req); } -static struct req +static void cmd_worker_add(int argc, char **argv) { struct worker wk = {0}; + struct apic req; - if (argc < 2) + if (argc < 3) usage(); - wk.name = argv[0]; - wk.desc = argv[1]; + wk.name = util_strdup(argv[1]); + wk.desc = util_strdup(argv[2]); - return req_worker_add(&wk); + if (apic_worker_save(&req, &wk) < 0) + util_die("abort: unable to save worker: %s\n", req.error); + + worker_finish(&wk); + apic_finish(&req); } -static struct req +static void cmd_worker_list(int argc, char **argv) { (void)argc; (void)argv; struct worker wk[SCI_WORKER_MAX]; - struct req req; - size_t wksz = UTIL_SIZE(wk); + struct apic req; + ssize_t wksz; - if ((req = req_worker_list(wk, &wksz)).status) - return req; + if ((wksz = apic_worker_list(&req, wk, UTIL_SIZE(wk))) < 0) + util_die("abort: unable to list worker: %s\n", req.error); for (size_t i = 0; i < wksz; ++i) { - printf("%-16s%d\n", "id:", wk[i].id); printf("%-16s%s\n", "name:", wk[i].name); printf("%-16s%s\n", "desc:", wk[i].desc); if (i + 1 < wksz) printf("\n"); + + worker_finish(&wk[i]); } - return req; + apic_finish(&req); } static struct { const char *name; - struct req (*exec)(int, char **); + void (*exec)(int, char **); } commands[] = { { "job-add", cmd_job_add }, { "job-todo", cmd_job_todo }, @@ -382,14 +332,21 @@ int main(int argc, char **argv) { - int ch, cmdfound = 0; + int ch; - setprogname("scictl"); + opterr = 0; + setenv("POSIXLY_CORRECT", "1", 1); - while ((ch = getopt(argc, argv, "s:")) != -1) { + while ((ch = getopt(argc, argv, "u:")) != -1) { switch (ch) { - case 's': - req_set_path(optarg); + case 'u': + util_strlcpy(apiconf.baseurl, optarg, sizeof (apiconf.baseurl)); + break; + case '?': + util_die("abort: invalid option: %c\n", ch); + break; + case ':': + util_die("abort: missing value for option %c\n", ch); break; default: break; @@ -399,26 +356,19 @@ argc -= optind; argv += optind; - if (argc <= 0) + optind = 1; + + if (argc < 1) usage(); if (strcmp(argv[0], "help") == 0) help(); for (size_t i = 0; commands[i].name; ++i) { - struct req res; - if (strcmp(commands[i].name, argv[0]) == 0) { - res = commands[i].exec(--argc, ++argv); - cmdfound = 1; - - if (res.status) - warnx("%s", json_string_value(json_object_get(res.msg, "error"))); - - req_finish(&res); - break; + commands[i].exec(argc, argv); + return 0; } } - if (!cmdfound) - errx(1, "abort: command %s not found", argv[0]); + util_die("abort: invalid command: %s\n", argv[0]); }