Mercurial > sci
view scictl/scictl.c @ 23:2cb228f23f53
misc: rework todo/jobs HTTP requests
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 21 Jul 2022 21:55:02 +0200 |
parents | dd078aea5d02 |
children | 34cbbd215ef7 |
line wrap: on
line source
/* * scictl.c -- main scictl(8) utility file * * Copyright (c) 2021 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <limits.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "apic.h" #include "config.h" #include "types.h" #include "util.h" static void usage(void) { fprintf(stderr, "usage: %s [-u baseurl] command [args...]\n", getprogname()); exit(1); } static void help(void) { 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 = NULL; size_t nr, consolesz = 0; if (strcmp(path, "-") == 0) fp = stdin; else if (!(fp = fopen(path, "r"))) util_die("abort: %s: %s\n", path, strerror(errno)); 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))) util_die("abort: %s\n", strerror(errno)); fclose(str); fclose(fp); return console; } static size_t extract(char *s, size_t w, size_t n, void *data) { return fwrite(s, w, n, data); } static void cmd_job_add(int argc, char **argv) { struct job job = {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(); if ((jobsz = apic_job_todo(&req, jobs, UTIL_SIZE(jobs), argv[1]))) util_die("abort: %s\n", req.error); for (size_t i = 0; i < jobsz; ++i) { printf("%-16s%jd\n", "id:", jobs[i].id); printf("%-16s%s\n", "tag:", jobs[i].tag); printf("%-16s%s\n", "project:", jobs[i].project_name); if (i + 1 < jobsz) printf("\n"); job_finish(&jobs[i]); } apic_finish(&req); } static void cmd_jobresult_add(int argc, char **argv) { struct jobresult res = {0}; 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(); pc.name = util_strdup(argv[1]); pc.desc = util_strdup(argv[2]); pc.url = util_strdup(argv[3]); pc.script = readfile(argv[4]); if (apic_project_save(&req, &pc) < 0) util_die("abort: unable to create project: %s\n", req.error); apic_finish(&req); project_finish(&pc); } static void cmd_project_update(int argc, char **argv) { struct project pc; struct apic req; if (argc < 4) usage(); if (apic_project_find(&req, &pc, argv[1]) < 0) util_die("abort: unable to find project: %s\n", req.error); 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])); 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 void cmd_project_info(int argc, char **argv) { struct project project = {0}; struct apic req; if (argc < 2) usage(); if (apic_project_find(&req, &project, argv[1]) < 0) util_die("abort: unable to find project: %s\n", req.error); 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); apic_finish(&req); project_finish(&project); } static void cmd_project_list(int argc, char **argv) { (void)argc; (void)argv; struct project projects[SCI_PROJECT_MAX] = {0}; struct apic req; ssize_t projectsz; 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%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]); } apic_finish(&req); } static void cmd_worker_add(int argc, char **argv) { struct worker wk = {0}; struct apic req; if (argc < 3) usage(); wk.name = util_strdup(argv[1]); wk.desc = util_strdup(argv[2]); 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 void cmd_worker_list(int argc, char **argv) { (void)argc; (void)argv; struct worker wk[SCI_WORKER_MAX]; struct apic req; ssize_t wksz; 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%s\n", "name:", wk[i].name); printf("%-16s%s\n", "desc:", wk[i].desc); if (i + 1 < wksz) printf("\n"); worker_finish(&wk[i]); } apic_finish(&req); } static struct { const char *name; void (*exec)(int, char **); } commands[] = { { "job-add", cmd_job_add }, { "job-todo", cmd_job_todo }, { "jobresult-add", cmd_jobresult_add }, { "project-add", cmd_project_add }, { "project-info", cmd_project_info }, { "project-list", cmd_project_list }, { "project-update", cmd_project_update }, { "worker-add", cmd_worker_add }, { "worker-list", cmd_worker_list }, { NULL, NULL } }; int main(int argc, char **argv) { int ch; opterr = 0; setenv("POSIXLY_CORRECT", "1", 1); while ((ch = getopt(argc, argv, "u:")) != -1) { switch (ch) { 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; } } argc -= optind; argv += optind; optind = 1; if (argc < 1) usage(); if (strcmp(argv[0], "help") == 0) help(); for (size_t i = 0; commands[i].name; ++i) { if (strcmp(commands[i].name, argv[0]) == 0) { commands[i].exec(argc, argv); return 0; } } util_die("abort: invalid command: %s\n", argv[0]); }