root/src/noit_check_rest.c

Revision 33756c85dc11cfd7fffd7acff7e4a3a2196fdc65, 20.2 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

fixes #232

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2009, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34 #include <assert.h>
35 #include <errno.h>
36 #include <libxml/parser.h>
37 #include <libxml/tree.h>
38 #include <libxml/xpath.h>
39 #include "noit_listener.h"
40 #include "noit_http.h"
41 #include "noit_rest.h"
42 #include "noit_check.h"
43 #include "noit_check_tools.h"
44 #include "noit_conf.h"
45 #include "noit_conf_private.h"
46
47 #define FAIL(a) do { error = (a); goto error; } while(0)
48
49 #define NODE_CONTENT(parent, k, v) do { \
50   xmlNodePtr tmp; \
51   if(v) { \
52     tmp = xmlNewNode(NULL, (xmlChar *)(k)); \
53     xmlNodeAddContent(tmp, (xmlChar *)(v)); \
54     xmlAddChild(parent, tmp); \
55   } \
56 } while(0)
57
58 xmlNodePtr
59 noit_check_state_as_xml(noit_check_t *check) {
60   xmlNodePtr state, tmp, metrics;
61   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
62   const char *k;
63   int klen;
64   void *data;
65   stats_t *c = &check->stats.current;
66
67   state = xmlNewNode(NULL, (xmlChar *)"state");
68   NODE_CONTENT(state, "running", NOIT_CHECK_RUNNING(check)?"true":"false");
69   NODE_CONTENT(state, "killed", NOIT_CHECK_KILLED(check)?"true":"false");
70   NODE_CONTENT(state, "configured",
71                NOIT_CHECK_CONFIGURED(check)?"true":"false");
72   NODE_CONTENT(state, "disabled", NOIT_CHECK_DISABLED(check)?"true":"false");
73   xmlAddChild(state, (tmp = xmlNewNode(NULL, (xmlChar *)"last_run")));
74   if(check->stats.current.whence.tv_sec) {
75     struct timeval f = check->stats.current.whence;
76     struct timeval n;
77     char timestr[20];
78     gettimeofday(&n, NULL);
79     snprintf(timestr, sizeof(timestr), "%0.3f",
80              n.tv_sec + (n.tv_usec / 1000000.0));
81     xmlSetProp(tmp, (xmlChar *)"now", (xmlChar *)timestr);
82     snprintf(timestr, sizeof(timestr), "%0.3f",
83              f.tv_sec + (f.tv_usec / 1000000.0));
84     xmlNodeAddContent(tmp, (xmlChar *)timestr);
85   }
86   if(c->available) { /* truth here means the check has been run */
87     char buff[20], *compiler_warning;
88     snprintf(buff, sizeof(buff), "%0.3f", (float)c->duration/1000.0);
89     compiler_warning = buff;
90     NODE_CONTENT(state, "runtime", compiler_warning);
91   }
92   NODE_CONTENT(state, "availability",
93                noit_check_available_string(c->available));
94   NODE_CONTENT(state, "state", noit_check_state_string(c->state));
95   NODE_CONTENT(state, "status", c->status ? c->status : "");
96   memset(&iter, 0, sizeof(iter));
97   xmlAddChild(state, (metrics = xmlNewNode(NULL, (xmlChar *)"metrics")));
98   while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) {
99     char buff[256];
100     metric_t *m = (metric_t *)data;
101     xmlAddChild(metrics, (tmp = xmlNewNode(NULL, (xmlChar *)"metric")));
102     xmlSetProp(tmp, (xmlChar *)"name", (xmlChar *)m->metric_name);
103     buff[0] = m->metric_type; buff[1] = '\0';
104     xmlSetProp(tmp, (xmlChar *)"type", (xmlChar *)buff);
105     if(m->metric_value.s) {
106       int rv;
107       rv = noit_stats_snprint_metric_value(buff, sizeof(buff), m);
108       if(rv < 0)
109         xmlSetProp(tmp, (xmlChar *)"error", (xmlChar *)"unknown type");
110       else
111         xmlNodeAddContent(tmp, (xmlChar *)buff);
112     }
113   }
114   return state;
115 }
116
117 static int
118 rest_show_check(noit_http_rest_closure_t *restc,
119                 int npats, char **pats) {
120   noit_http_session_ctx *ctx = restc->http_ctx;
121   xmlXPathObjectPtr pobj = NULL;
122   xmlXPathContextPtr xpath_ctxt = NULL;
123   xmlDocPtr doc = NULL;
124   xmlNodePtr node, root, attr, config, state, tmp, anode;
125   uuid_t checkid;
126   noit_check_t *check;
127   char xpath[1024], *uuid_conf, *module, *value;
128   int rv, cnt, error_code = 500;
129   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
130   const char *k;
131   int klen;
132   void *data;
133   noit_hash_table *configh;
134
135   if(npats != 2) goto error;
136
137   rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]);
138   if(rv == 0) goto not_found;
139   if(rv < 0) goto error;
140
141   noit_conf_xml_xpath(NULL, &xpath_ctxt);
142   pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt);
143   if(!pobj || pobj->type != XPATH_NODESET ||
144      xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto not_found;
145   cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
146   if(cnt != 1) goto error;
147
148   node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0);
149   uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid");
150   if(!uuid_conf || uuid_parse(uuid_conf, checkid)) goto error;
151
152   doc = xmlNewDoc((xmlChar *)"1.0");
153   root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL);
154   xmlDocSetRootElement(doc, root);
155
156 #define MYATTR(node,a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b))
157 #define INHERIT(node,a,n,b) \
158   _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b))
159 #define SHOW_ATTR(parent, node, a) do { \
160   xmlNodePtr anode = NULL; \
161   char *value = NULL; \
162   INHERIT(node, a, anode, value); \
163   if(value != NULL) { \
164     int clen, plen;\
165     const char *cpath, *apath; \
166     xmlNodePtr child; \
167     cpath = node ? (char *)xmlGetNodePath(node) : ""; \
168     apath = anode ? (char *)xmlGetNodePath(anode) : ""; \
169     clen = strlen(cpath); \
170     plen = strlen("/noit/checks"); \
171     child = xmlNewNode(NULL, (xmlChar *)#a); \
172     xmlNodeAddContent(child, (xmlChar *)value); \
173     if(!strncmp(cpath, apath, clen) && apath[clen] == '/') { \
174     } \
175     else { \
176       xmlSetProp(child, (xmlChar *)"inherited", (xmlChar *)apath+plen); \
177     } \
178     xmlAddChild(parent, child); \
179   } \
180 } while(0)
181
182   attr = xmlNewNode(NULL, (xmlChar *)"attributes");
183   xmlAddChild(root, attr);
184
185   SHOW_ATTR(attr,node,uuid);
186
187   /* Name is odd, it falls back transparently to module */
188   if(!INHERIT(node, module, tmp, module)) module = NULL;
189   xmlAddChild(attr, (tmp = xmlNewNode(NULL, (xmlChar *)"name")));
190   if(MYATTR(node, name, anode, value))
191     xmlNodeAddContent(tmp, (xmlChar *)value);
192   else if(module)
193     xmlNodeAddContent(tmp, (xmlChar *)module);
194
195   SHOW_ATTR(attr,node,module);
196   SHOW_ATTR(attr,node,target);
197   SHOW_ATTR(attr,node,period);
198   SHOW_ATTR(attr,node,timeout);
199   SHOW_ATTR(attr,node,oncheck);
200   SHOW_ATTR(attr,node,filterset);
201   SHOW_ATTR(attr,node,disable);
202
203   /* Add the config */
204   config = xmlNewNode(NULL, (xmlChar *)"config");
205   configh = noit_conf_get_hash(node, "config");
206   while(noit_hash_next(configh, &iter, &k, &klen, &data))
207     NODE_CONTENT(config, k, data);
208   noit_hash_destroy(configh, free, free);
209   free(configh);
210   xmlAddChild(root, config);
211
212   /* Add the state */
213   check = noit_poller_lookup(checkid);
214   if(!check) {
215     state = xmlNewNode(NULL, (xmlChar *)"state");
216     xmlSetProp(state, (xmlChar *)"error", (xmlChar *)"true");
217   }
218   else
219     state = noit_check_state_as_xml(check);
220   xmlAddChild(root, state);
221   noit_http_response_ok(ctx, "text/xml");
222   noit_http_response_xml(ctx, doc);
223   noit_http_response_end(ctx);
224   goto cleanup;
225
226  not_found:
227   noit_http_response_not_found(ctx, "text/html");
228   noit_http_response_end(ctx);
229   goto cleanup;
230
231  error:
232   noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
233   noit_http_response_end(ctx);
234   goto cleanup;
235
236  cleanup:
237   if(pobj) xmlXPathFreeObject(pobj);
238   if(doc) xmlFreeDoc(doc);
239   return 0;
240 }
241
242 int
243 noit_validate_check_rest_post(xmlDocPtr doc, xmlNodePtr *a, xmlNodePtr *c,
244                               const char **error) {
245   xmlNodePtr root, tl, an;
246   int name=0, module=0, target=0, period=0, timeout=0, filterset=0;
247   *a = *c = NULL;
248   root = xmlDocGetRootElement(doc);
249   if(!root || strcmp((char *)root->name, "check")) return 0;
250   for(tl = root->children; tl; tl = tl->next) {
251     if(!strcmp((char *)tl->name, "attributes")) {
252       *a = tl;
253       for(an = tl->children; an; an = an->next) {
254 #define CHECK_N_SET(a) if(!strcmp((char *)an->name, #a))
255         CHECK_N_SET(name) {
256           xmlChar *tmp;
257           pcre *valid_name = noit_conf_get_valid_name_checker();
258           int ovector[30], valid;
259           tmp = xmlNodeGetContent(an);
260           valid = (pcre_exec(valid_name, NULL,
261                              (char *)tmp, strlen((char *)tmp), 0, 0,
262                              ovector, sizeof(ovector)/sizeof(*ovector)) > 0);
263           xmlFree(tmp);
264           if(!valid) { *error = "invalid name"; return 0; }
265           name = 1;
266         }
267         else CHECK_N_SET(module) module = 1; /* This is validated by called */
268         else CHECK_N_SET(target) {
269           int valid;
270           xmlChar *tmp;
271           tmp = xmlNodeGetContent(an);
272           valid = noit_check_is_valid_target((char *)tmp);
273           xmlFree(tmp);
274           if(!valid) { *error = "invalid target"; return 0; }
275           target = 1;
276         }
277         else CHECK_N_SET(period) {
278           int pint;
279           xmlChar *tmp;
280           tmp = xmlNodeGetContent(an);
281           pint = noit_conf_string_to_int((char *)tmp);
282           xmlFree(tmp);
283           if(pint < 5000 || pint > 300000) {
284             *error = "invalid period";
285             return 0;
286           }
287           period = 1;
288         }
289         else CHECK_N_SET(timeout) {
290           int pint;
291           xmlChar *tmp;
292           tmp = xmlNodeGetContent(an);
293           pint = noit_conf_string_to_int((char *)tmp);
294           xmlFree(tmp);
295           if(pint < 0 || pint > 300000) {
296             *error = "invalid timeout";
297             return 0;
298           }
299           timeout = 1;
300         }
301         else CHECK_N_SET(filterset) filterset = 1;
302         else CHECK_N_SET(disable) { /* not required */
303           int valid;
304           xmlChar *tmp;
305           tmp = xmlNodeGetContent(an);
306           valid = (!strcasecmp((char *)tmp, "true") ||
307                    !strcasecmp((char *)tmp, "on") ||
308                    !strcasecmp((char *)tmp, "false") ||
309                    !strcasecmp((char *)tmp, "off"));
310           xmlFree(tmp);
311           if(!valid) { *error = "bad disable parameter"; return 0; }
312           target = 1;
313         }
314         else return 0;
315       }
316     }
317     else if(!strcmp((char *)tl->name, "config")) {
318       *c = tl;
319       /* Noop, anything goes */
320     }
321     else return 0;
322   }
323   if(name && module && target && period && timeout && filterset) return 1;
324   *error = "insufficient information";
325   return 0;
326 }
327 static void
328 configure_xml_check(xmlNodePtr check, xmlNodePtr a, xmlNodePtr c) {
329   xmlNodePtr n, config, oldconfig;
330   for(n = a->children; n; n = n->next) {
331 #define ATTR2PROP(attr) do { \
332   if(!strcmp((char *)n->name, #attr)) { \
333     xmlChar *v = xmlNodeGetContent(n); \
334     if(v) xmlSetProp(check, n->name, v); \
335     else xmlUnsetProp(check, n->name); \
336     if(v) xmlFree(v); \
337   } \
338 } while(0)
339     ATTR2PROP(name);
340     ATTR2PROP(target);
341     ATTR2PROP(module);
342     ATTR2PROP(period);
343     ATTR2PROP(timeout);
344     ATTR2PROP(disable);
345     ATTR2PROP(filterset);
346   }
347   for(oldconfig = check->children; oldconfig; oldconfig = oldconfig->next)
348     if(!strcmp((char *)oldconfig->name, "config")) break;
349   config = xmlNewNode(NULL, (xmlChar *)"config");
350   if(c) {
351     xmlAttrPtr inherit;
352     if((inherit = xmlHasProp(c, (xmlChar *)"inherit")) != NULL &&
353         inherit->children && inherit->children->content)
354       xmlSetProp(config, (xmlChar *)"inherit", inherit->children->content);
355     for(n = c->children; n; n = n->next) {
356       xmlChar *v = xmlNodeGetContent(n);
357       xmlNodePtr co = xmlNewNode(NULL, n->name);
358       xmlNodeAddContent(co, v);
359       xmlFree(v);
360       xmlAddChild(config, co);
361     }
362   }
363   if(oldconfig) {
364     xmlReplaceNode(oldconfig, config);
365     xmlFreeNode(oldconfig);
366   }
367   else xmlAddChild(check, config);
368 }
369 static xmlNodePtr
370 make_conf_path(char *path) {
371   xmlNodePtr start, tmp;
372   char fullpath[1024], *tok, *brk;
373   if(!path || strlen(path) < 1) return NULL;
374   snprintf(fullpath, sizeof(fullpath), "%s", path+1);
375   fullpath[strlen(fullpath)-1] = '\0';
376   start = noit_conf_get_section(NULL, "/noit/checks");
377   if(!start) return NULL;
378   for (tok = strtok_r(fullpath, "/", &brk);
379        tok;
380        tok = strtok_r(NULL, "/", &brk)) {
381     if(!xmlValidateNameValue((xmlChar *)tok)) return NULL;
382     if(!strcmp(tok, "check")) return NULL;  /* These two paths */
383     if(!strcmp(tok, "config")) return NULL; /* are off limits. */
384     for (tmp = start->children; tmp; tmp = tmp->next) {
385       if(!strcmp((char *)tmp->name, tok)) break;
386     }
387     if(!tmp) {
388       tmp = xmlNewNode(NULL, (xmlChar *)tok);
389       xmlAddChild(start, tmp);
390     }
391     start = tmp;
392   }
393   return start;
394 }
395 static int
396 rest_delete_check(noit_http_rest_closure_t *restc,
397                   int npats, char **pats) {
398   noit_http_session_ctx *ctx = restc->http_ctx;
399   xmlXPathObjectPtr pobj = NULL;
400   xmlXPathContextPtr xpath_ctxt = NULL;
401   xmlNodePtr node;
402   uuid_t checkid;
403   noit_check_t *check;
404   const char *error;
405   char xpath[1024], *uuid_conf;
406   int rv, cnt, error_code = 500;
407   noit_boolean exists = noit_false;
408
409   if(npats != 2) goto error;
410
411   if(uuid_parse(pats[1], checkid)) goto error;
412   check = noit_poller_lookup(checkid);
413   if(check)
414     exists = noit_true;
415
416   rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]);
417   if(rv == 0) FAIL("uuid not valid");
418   if(rv < 0) FAIL("Tricky McTrickster... No");
419
420   noit_conf_xml_xpath(NULL, &xpath_ctxt);
421   pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt);
422   if(!pobj || pobj->type != XPATH_NODESET ||
423      xmlXPathNodeSetIsEmpty(pobj->nodesetval)) {
424     if(exists) { error_code = 403; FAIL("uuid not yours"); }
425     goto not_found;
426   }
427   cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
428   if(cnt != 1) FAIL("internal error, |checkid| > 1");
429   node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0);
430   uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid");
431   if(!uuid_conf || strcasecmp(uuid_conf, pats[1]))
432     FAIL("internal error uuid");
433
434   /* delete this here */
435   noit_poller_deschedule(check->checkid);
436   xmlUnlinkNode(node);
437   xmlFreeNode(node);
438   if(noit_conf_write_file(NULL) != 0)
439     noitL(noit_error, "local config write failed\n");
440   noit_conf_mark_changed();
441   noit_http_response_ok(ctx, "text/html");
442   noit_http_response_end(ctx);
443   goto cleanup;
444
445  not_found:
446   noit_http_response_not_found(ctx, "text/html");
447   noit_http_response_end(ctx);
448   goto cleanup;
449
450  error:
451   noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
452   noit_http_response_end(ctx);
453   goto cleanup;
454
455  cleanup:
456   if(pobj) xmlXPathFreeObject(pobj);
457   return 0;
458 }
459
460 static int
461 rest_set_check(noit_http_rest_closure_t *restc,
462                int npats, char **pats) {
463   noit_http_session_ctx *ctx = restc->http_ctx;
464   xmlXPathObjectPtr pobj = NULL;
465   xmlXPathContextPtr xpath_ctxt = NULL;
466   xmlDocPtr doc = NULL, indoc = NULL;
467   xmlNodePtr node, root, attr, config, parent;
468   uuid_t checkid;
469   noit_check_t *check;
470   char xpath[1024], *uuid_conf;
471   int rv, cnt, error_code = 500, complete = 0, mask = 0;
472   const char *error = "internal error";
473   noit_boolean exists = noit_false;
474
475   if(npats != 2) goto error;
476
477   indoc = rest_get_xml_upload(restc, &mask, &complete);
478   if(!complete) return mask;
479   if(indoc == NULL) FAIL("xml parse error");
480   if(!noit_validate_check_rest_post(indoc, &attr, &config, &error)) goto error;
481
482   if(uuid_parse(pats[1], checkid)) goto error;
483   check = noit_poller_lookup(checkid);
484   if(check)
485     exists = noit_true;
486
487   rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]);
488   if(rv == 0) FAIL("uuid not valid");
489   if(rv < 0) FAIL("Tricky McTrickster... No");
490
491   noit_conf_xml_xpath(NULL, &xpath_ctxt);
492   pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt);
493   if(!pobj || pobj->type != XPATH_NODESET ||
494      xmlXPathNodeSetIsEmpty(pobj->nodesetval)) {
495     if(exists) { error_code = 403; FAIL("uuid not yours"); }
496     else {
497       char *target = NULL, *name = NULL, *module = NULL;
498       noit_module_t *m;
499       xmlNodePtr newcheck, a;
500       /* make sure this isn't a dup */
501       for(a = attr->children; a; a = a->next) {
502         if(!strcmp((char *)a->name, "target"))
503           target = (char *)xmlNodeGetContent(a);
504         if(!strcmp((char *)a->name, "name"))
505           name = (char *)xmlNodeGetContent(a);
506         if(!strcmp((char *)a->name, "module"))
507           module = (char *)xmlNodeGetContent(a);
508       }
509       exists = (noit_poller_lookup_by_name(target, name) != NULL);
510       m = noit_module_lookup(module);
511       xmlFree(target);
512       xmlFree(name);
513       xmlFree(module);
514       if(exists) FAIL("target`name already registered");
515       if(!m) FAIL("module does not exist");
516       /* create a check here */
517       newcheck = xmlNewNode(NULL, (xmlChar *)"check");
518       xmlSetProp(newcheck, (xmlChar *)"uuid", (xmlChar *)pats[1]);
519       configure_xml_check(newcheck, attr, config);
520       parent = make_conf_path(pats[0]);
521       if(!parent) FAIL("invalid path");
522       xmlAddChild(parent, newcheck);
523     }
524   }
525   if(exists) {
526     int module_change;
527     char *target = NULL, *name = NULL, *module = NULL;
528     xmlNodePtr a;
529     noit_check_t *ocheck;
530
531     cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
532     if(cnt != 1) FAIL("internal error, |checkid| > 1");
533     node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0);
534     uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid");
535     if(!uuid_conf || strcasecmp(uuid_conf, pats[1]))
536       FAIL("internal error uuid");
537
538     /* make sure this isn't a dup */
539     for(a = attr->children; a; a = a->next) {
540       if(!strcmp((char *)a->name, "target"))
541         target = (char *)xmlNodeGetContent(a);
542       if(!strcmp((char *)a->name, "name"))
543         name = (char *)xmlNodeGetContent(a);
544       if(!strcmp((char *)a->name, "module"))
545         module = (char *)xmlNodeGetContent(a);
546     }
547     ocheck = noit_poller_lookup_by_name(target, name);
548     module_change = strcmp(check->module, module);
549     xmlFree(target);
550     xmlFree(name);
551     xmlFree(module);
552     if(ocheck && ocheck != check) FAIL("new target`name would collide");
553     if(module_change) FAIL("cannot change module");
554     configure_xml_check(node, attr, config);
555     parent = make_conf_path(pats[0]);
556     if(!parent) FAIL("invalid path");
557     xmlUnlinkNode(node);
558     xmlAddChild(parent, node);
559   }
560
561   if(noit_conf_write_file(NULL) != 0)
562     noitL(noit_error, "local config write failed\n");
563   noit_conf_mark_changed();
564   noit_poller_reload(xpath);
565   if(restc->call_closure_free) restc->call_closure_free(restc->call_closure);
566   restc->call_closure_free = NULL;
567   restc->call_closure = NULL;
568   if(pobj) xmlXPathFreeObject(pobj);
569   if(doc) xmlFreeDoc(doc);
570   restc->fastpath = rest_show_check;
571   return restc->fastpath(restc, restc->nparams, restc->params);
572
573  error:
574   noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
575   doc = xmlNewDoc((xmlChar *)"1.0");
576   root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL);
577   xmlDocSetRootElement(doc, root);
578   xmlNodeAddContent(root, (xmlChar *)error);
579   noit_http_response_xml(ctx, doc);
580   noit_http_response_end(ctx);
581   goto cleanup;
582
583  cleanup:
584   if(pobj) xmlXPathFreeObject(pobj);
585   if(doc) xmlFreeDoc(doc);
586   return 0;
587 }
588
589 void
590 noit_check_rest_init() {
591   assert(noit_http_rest_register_auth(
592     "GET", "/checks/", "^show(/.*)(?<=/)(" UUID_REGEX ")$",
593     rest_show_check, noit_http_rest_client_cert_auth
594   ) == 0);
595   assert(noit_http_rest_register_auth(
596     "PUT", "/checks/", "^set(/.*)(?<=/)(" UUID_REGEX ")$",
597     rest_set_check, noit_http_rest_client_cert_auth
598   ) == 0);
599   assert(noit_http_rest_register_auth(
600     "DELETE", "/checks/", "^delete(/.*)(?<=/)(" UUID_REGEX ")$",
601     rest_delete_check, noit_http_rest_client_cert_auth
602   ) == 0);
603 }
604
Note: See TracBrowser for help on using the browser.