root/src/noit_check_rest.c

Revision 408e1b41bdb6ca5a28363b80d3055a602c80dcc3, 20.5 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

require the filterset to exist

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