diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-02-20 22:33:00 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-02-20 22:42:46 +0200 |
commit | 46130027d8e6e91951226456174e6ad471ddc50f (patch) | |
tree | f88ce6edd9b078b5f331497bc452525f3c4c9c94 | |
parent | e6902abfddb4d7b16dc9a4231a3781f354a08cd5 (diff) | |
download | pies-46130027d8e6e91951226456174e6ad471ddc50f.tar.gz pies-46130027d8e6e91951226456174e6ad471ddc50f.tar.bz2 |
Improve control interface
This commit implements the following operations on the new /conf endpoints:
GET /conf/runtime - List configuration
PUT /conf/runtime - Reload configuration
POST /conf/runtime - Post new configuration
GET /conf/files - List configuration files
DELETE /conf/files - Delete some or all configuration files
from the list
POST /conf/files - Install new configuration file
Piesctl supports the following new commands:
piesctl config reload
piesctl config file clear
piesctl config file add SYNTAX NAME
piesctl config file del[ete] NAME [NAME...]
piesctl config file list
* src/ctl.c (res_conf): New function.
(restab): New endpoint /conf
* src/pies.c (config_file_add): Set free_entry.
(config_file_remove, config_file_remove_all)
(config_file_list_serialize): New functions.
(pies_config_parse): Bail out if tree processing fails.
(pies_reload): Remove unused function.
(main): Redo ACTION_RELOAD handling.
Handle ACTION_COMMIT.
* src/pies.h (ACTION_COMMIT): New action.
(config_file_remove, config_file_remove_all)
(config_file_list_serialize)
(pies_read_config, progman_gc): New protos.
* src/piesctl.c (cmdline_parser_state): New struct
(next_token, peek_token): Take ptr to cmdline_parser_state as argument.
(parse_error, require_token, assert_eol)
(piesctl_format): New functions.
(parse_condition_to_uri): Rewrite using piesctl_format.
New subcommand: config.
Improve help output.
-rw-r--r-- | src/ctl.c | 246 | ||||
-rw-r--r-- | src/pies.c | 88 | ||||
-rw-r--r-- | src/pies.h | 10 | ||||
-rw-r--r-- | src/piesctl.c | 612 |
4 files changed, 787 insertions, 169 deletions
@@ -910,6 +910,8 @@ static void res_programs (struct ctlio *, enum http_method, char const *, | |||
910 | struct json_value *); | 910 | struct json_value *); |
911 | static void res_runlevel (struct ctlio *, enum http_method, char const *, | 911 | static void res_runlevel (struct ctlio *, enum http_method, char const *, |
912 | struct json_value *); | 912 | struct json_value *); |
913 | static void res_conf (struct ctlio *, enum http_method, char const *, | ||
914 | struct json_value *); | ||
913 | 915 | ||
914 | static int pred_sysvinit (void); | 916 | static int pred_sysvinit (void); |
915 | 917 | ||
@@ -926,6 +928,7 @@ struct ctlio_resource | |||
926 | static struct ctlio_resource restab[] = { | 928 | static struct ctlio_resource restab[] = { |
927 | #define S(s) #s, (sizeof (#s)-1) | 929 | #define S(s) #s, (sizeof (#s)-1) |
928 | { S(/instance), CTL_ADMIN_STATE, NULL, res_instance }, | 930 | { S(/instance), CTL_ADMIN_STATE, NULL, res_instance }, |
931 | { S(/conf), CTL_ADMIN_STATE, NULL, res_conf }, | ||
929 | { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, NULL, | 932 | { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, NULL, |
930 | res_programs }, | 933 | res_programs }, |
931 | { S(/runlevel), CTL_ADMIN_STATE, pred_sysvinit, res_runlevel }, | 934 | { S(/runlevel), CTL_ADMIN_STATE, pred_sysvinit, res_runlevel }, |
@@ -2107,4 +2110,247 @@ res_runlevel (struct ctlio *io, enum http_method meth, | |||
2107 | else | 2110 | else |
2108 | ctlio_reply (io, 405, NULL); | 2111 | ctlio_reply (io, 405, NULL); |
2109 | } | 2112 | } |
2113 | |||
2114 | /* GET /conf/runtime - List configuration | ||
2115 | * PUT /conf/runtime - Reload configuration | ||
2116 | * POST /conf/runtime - Post new configuration | ||
2117 | * | ||
2118 | * GET /conf/files - List configuration files | ||
2119 | * DELETE /conf/files - Delete some or all configuration files | ||
2120 | * from the list | ||
2121 | * POST /conf/files - Install new list configuration file | ||
2122 | */ | ||
2123 | |||
2124 | static void | ||
2125 | conf_list_files (struct ctlio *io) | ||
2126 | { | ||
2127 | io->output.reply = json_new_array (); | ||
2128 | io->code = 200; | ||
2129 | config_file_list_serialize (io->output.reply); | ||
2130 | } | ||
2110 | 2131 | ||
2132 | static void | ||
2133 | conf_add_file (struct ctlio *io, struct json_value *json) | ||
2134 | { | ||
2135 | struct json_value *v; | ||
2136 | struct config_syntax *synt; | ||
2137 | |||
2138 | if (json->type != json_object) | ||
2139 | { | ||
2140 | ctlio_reply (io, 400, NULL); | ||
2141 | return; | ||
2142 | } | ||
2143 | if (json_object_get (json, "syntax", &v) || v->type != json_string) | ||
2144 | { | ||
2145 | ctlio_reply (io, 400, NULL); | ||
2146 | return; | ||
2147 | } | ||
2148 | synt = str_to_config_syntax (v->v.s); | ||
2149 | if (!synt) | ||
2150 | { | ||
2151 | ctlio_reply (io, 400, NULL); | ||
2152 | return; | ||
2153 | } | ||
2154 | if (json_object_get (json, "file", &v) || v->type != json_string) | ||
2155 | { | ||
2156 | ctlio_reply (io, 400, NULL); | ||
2157 | return; | ||
2158 | } | ||
2159 | |||
2160 | config_file_add (synt, v->v.s); | ||
2161 | ctlio_reply (io, 201, NULL); | ||
2162 | } | ||
2163 | |||
2164 | static void | ||
2165 | conf_delete_files (struct ctlio *io, struct json_value *json) | ||
2166 | { | ||
2167 | io->code = 200; | ||
2168 | io->output.reply = json_reply_create (); | ||
2169 | |||
2170 | if ((json->type == json_bool && json->v.b == 1) | ||
2171 | || (json->type == json_arr && json_array_size (json) == 0)) | ||
2172 | { | ||
2173 | config_file_remove_all (); | ||
2174 | json_object_set_string (io->output.reply, "status", "OK"); | ||
2175 | json_object_set_string (io->output.reply, "message", | ||
2176 | "file list cleared"); | ||
2177 | } | ||
2178 | else if (json->type == json_arr) | ||
2179 | { | ||
2180 | size_t i, n, fails = 0; | ||
2181 | struct json_value *reply; | ||
2182 | |||
2183 | n = json_array_size (json); | ||
2184 | |||
2185 | /* Check request */ | ||
2186 | for (i = 0; i < n; i++) | ||
2187 | { | ||
2188 | struct json_value *val; | ||
2189 | json_array_get (json, i, &val); | ||
2190 | if (val->type != json_string) | ||
2191 | { | ||
2192 | json_object_set_string (io->output.reply, "status", "ER"); | ||
2193 | json_object_set_string (io->output.reply, "error_message", | ||
2194 | "malformed request"); | ||
2195 | return; | ||
2196 | } | ||
2197 | } | ||
2198 | |||
2199 | reply = json_new_array (); | ||
2200 | /* Process request */ | ||
2201 | for (i = 0; i < n; i++) | ||
2202 | { | ||
2203 | struct json_value *val; | ||
2204 | int rc; | ||
2205 | |||
2206 | json_array_get (json, i, &val); | ||
2207 | |||
2208 | rc = config_file_remove (val->v.s); | ||
2209 | if (rc) | ||
2210 | ++fails; | ||
2211 | json_array_append (reply, json_new_bool (!rc)); | ||
2212 | } | ||
2213 | |||
2214 | if (fails == n) | ||
2215 | { | ||
2216 | json_object_set_string (io->output.reply, "status", "ER"); | ||
2217 | json_object_set_string (io->output.reply, "error_message", | ||
2218 | "no matching files found"); | ||
2219 | json_value_free (reply); | ||
2220 | } | ||
2221 | else | ||
2222 | { | ||
2223 | json_object_set_string (io->output.reply, "status", "OK"); | ||
2224 | if (fails) | ||
2225 | { | ||
2226 | json_object_set_string (io->output.reply, "error_message", | ||
2227 | "some files not removed"); | ||
2228 | json_object_set (io->output.reply, "result", reply); | ||
2229 | } | ||
2230 | else | ||
2231 | json_value_free (reply); | ||
2232 | } | ||
2233 | } | ||
2234 | } | ||
2235 | |||
2236 | static void (*saved_diag_fun)(grecs_locus_t const *, int, int, | ||
2237 | const char *msg); | ||
2238 | static struct json_value *messages; | ||
2239 | |||
2240 | static void | ||
2241 | reload_diag_fun (grecs_locus_t const *locus, int err, int errcode, | ||
2242 | const char *text) | ||
2243 | { | ||
2244 | struct json_value *msg = json_new_object (); | ||
2245 | |||
2246 | if (locus) | ||
2247 | { | ||
2248 | struct json_value *ar = json_new_array (); | ||
2249 | json_array_append (ar, json_new_string (locus->beg.file)); | ||
2250 | json_array_append (ar, json_new_string (locus->end.file)); | ||
2251 | json_object_set (msg, "file", ar); | ||
2252 | |||
2253 | ar = json_new_array (); | ||
2254 | json_array_append (ar, json_new_number (locus->beg.line)); | ||
2255 | json_array_append (ar, json_new_number (locus->end.line)); | ||
2256 | json_object_set (msg, "line", ar); | ||
2257 | |||
2258 | ar = json_new_array (); | ||
2259 | json_array_append (ar, json_new_number (locus->beg.col)); | ||
2260 | json_array_append (ar, json_new_number (locus->end.col)); | ||
2261 | json_object_set (msg, "col", ar); | ||
2262 | |||
2263 | json_object_set (msg, "error", json_new_bool (err)); | ||
2264 | |||
2265 | if (errcode) | ||
2266 | { | ||
2267 | json_object_set (msg, "syserrno", | ||
2268 | json_new_number (errno)); | ||
2269 | json_object_set (msg, "syserrstr", | ||
2270 | json_new_string (strerror (errno))); | ||
2271 | } | ||
2272 | |||
2273 | json_object_set (msg, "message", json_new_string (text)); | ||
2274 | json_array_append (messages, msg); | ||
2275 | } | ||
2276 | |||
2277 | saved_diag_fun (locus, err, errcode, text); | ||
2278 | } | ||
2279 | |||
2280 | static void | ||
2281 | conf_reload (struct ctlio *io) | ||
2282 | { | ||
2283 | io->code = 200; | ||
2284 | io->output.reply = json_reply_create (); | ||
2285 | |||
2286 | saved_diag_fun = grecs_print_diag_fun; | ||
2287 | grecs_print_diag_fun = reload_diag_fun; | ||
2288 | messages = json_new_array (); | ||
2289 | if (pies_read_config ()) | ||
2290 | { | ||
2291 | json_object_set_string (io->output.reply, "status", "ER"); | ||
2292 | json_object_set_string (io->output.reply, "error_message", | ||
2293 | "configuration syntax error"); | ||
2294 | } | ||
2295 | else | ||
2296 | { | ||
2297 | pies_schedule_action (ACTION_COMMIT); | ||
2298 | json_object_set_string (io->output.reply, "status", "OK"); | ||
2299 | json_object_set_string (io->output.reply, "message", | ||
2300 | "reload successful"); | ||
2301 | } | ||
2302 | json_object_set (io->output.reply, "parser_messages", messages); | ||
2303 | grecs_print_diag_fun = saved_diag_fun; | ||
2304 | } | ||
2305 | |||
2306 | static void | ||
2307 | res_conf (struct ctlio *io, enum http_method meth, | ||
2308 | char const *uri, struct json_value *json) | ||
2309 | { | ||
2310 | if (!uri) | ||
2311 | { | ||
2312 | ctlio_reply (io, 404, NULL); | ||
2313 | return; | ||
2314 | } | ||
2315 | |||
2316 | ++uri; /* skip leading / */ | ||
2317 | if (strcmp (uri, "files") == 0) | ||
2318 | { | ||
2319 | switch (meth) | ||
2320 | { | ||