func startEventMonitor(sc *serfclient.RPCClient, errch chan<- error) { ch := make(chan map[string]interface{}, 10) sh, err := sc.Stream("*", ch) if err != nil { errch <- err return } errch <- nil defer sc.Stop(sh) // watch the events and queries for e := range ch { logger.Debugf("Got an event: %v", e) eName, _ := e["Name"] switch eName { case "node_status": jsonPayload := make(map[string]string) err = json.Unmarshal(e["Payload"].([]byte), &jsonPayload) if err != nil { logger.Errorf(err.Error()) continue } n, _ := node.Get(jsonPayload["node"]) if n == nil { logger.Errorf("No node %s", jsonPayload["node"]) continue } err = n.UpdateStatus(jsonPayload["status"]) if err != nil { logger.Errorf(err.Error()) continue } r := map[string]string{"response": "ok"} response, _ := json.Marshal(r) var id uint64 switch t := e["ID"].(type) { case int64: id = uint64(t) case uint64: id = t default: logger.Errorf("node_status ID %v type %T not int64 or uint64", e["ID"], e["ID"]) continue } sc.Respond(id, response) } } return }
func nodeHandling(w http.ResponseWriter, r *http.Request) map[string]string { /* We're dealing with nodes, then. */ nodeResponse := make(map[string]string) opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID")) if oerr != nil { jsonErrorReport(w, r, oerr.Error(), oerr.Status()) return nil } switch r.Method { case "GET": if opUser.IsValidator() { jsonErrorReport(w, r, "You are not allowed to take this action.", http.StatusForbidden) return nil } nodeList := node.GetList() for _, k := range nodeList { itemURL := fmt.Sprintf("/nodes/%s", k) nodeResponse[k] = util.CustomURL(itemURL) } case "POST": if opUser.IsValidator() { jsonErrorReport(w, r, "You are not allowed to take this action.", http.StatusForbidden) return nil } nodeData, jerr := parseObjJSON(r.Body) if jerr != nil { jsonErrorReport(w, r, jerr.Error(), http.StatusBadRequest) return nil } nodeName, sterr := util.ValidateAsString(nodeData["name"]) if sterr != nil { jsonErrorReport(w, r, sterr.Error(), http.StatusBadRequest) return nil } chefNode, _ := node.Get(nodeName) if chefNode != nil { httperr := fmt.Errorf("Node already exists") jsonErrorReport(w, r, httperr.Error(), http.StatusConflict) return nil } var nerr util.Gerror chefNode, nerr = node.NewFromJSON(nodeData) if nerr != nil { jsonErrorReport(w, r, nerr.Error(), nerr.Status()) return nil } err := chefNode.Save() if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return nil } err = chefNode.UpdateStatus("new") if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return nil } if lerr := loginfo.LogEvent(opUser, chefNode, "create"); lerr != nil { jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError) return nil } nodeResponse["uri"] = util.ObjURL(chefNode) w.WriteHeader(http.StatusCreated) default: jsonErrorReport(w, r, "Method not allowed for nodes", http.StatusMethodNotAllowed) return nil } return nodeResponse }
func statusHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID")) if oerr != nil { jsonErrorReport(w, r, oerr.Error(), oerr.Status()) return } if !opUser.IsAdmin() { jsonErrorReport(w, r, "You must be an admin to do that", http.StatusForbidden) return } pathArray := splitPath(r.URL.Path) if len(pathArray) < 3 { jsonErrorReport(w, r, "Bad request", http.StatusBadRequest) return } var statusResponse interface{} switch r.Method { case "GET": /* pathArray[1] will tell us what operation we're doing */ switch pathArray[1] { // /status/all/nodes case "all": if len(pathArray) != 3 { jsonErrorReport(w, r, "Bad request", http.StatusBadRequest) return } if pathArray[2] != "nodes" { jsonErrorReport(w, r, "Invalid object to get status for", http.StatusBadRequest) return } nodes := node.AllNodes() sr := make([]map[string]string, len(nodes)) for i, n := range nodes { ns, err := n.LatestStatus() if err != nil { nsbad := make(map[string]string) nsbad["node_name"] = n.Name nsbad["status"] = "no record" sr[i] = nsbad continue } sr[i] = ns.ToJSON() nsurl := fmt.Sprintf("/status/node/%s/latest", n.Name) sr[i]["url"] = util.CustomURL(nsurl) } statusResponse = sr // /status/node/<nodeName>/(all|latest) case "node": if len(pathArray) != 4 { jsonErrorReport(w, r, "Bad request", http.StatusBadRequest) return } nodeName := pathArray[2] op := pathArray[3] n, gerr := node.Get(nodeName) if gerr != nil { jsonErrorReport(w, r, gerr.Error(), gerr.Status()) return } switch op { case "latest": ns, err := n.LatestStatus() if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } statusResponse = ns.ToJSON() case "all": ns, err := n.AllStatuses() if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } sr := make([]map[string]string, len(ns)) for i, v := range ns { sr[i] = v.ToJSON() } statusResponse = sr default: jsonErrorReport(w, r, "Bad request", http.StatusBadRequest) return } default: jsonErrorReport(w, r, "Bad request", http.StatusBadRequest) return } default: jsonErrorReport(w, r, "Method not allowed", http.StatusMethodNotAllowed) return } enc := json.NewEncoder(w) if err := enc.Encode(&statusResponse); err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) } }
func nodeHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") nodeName := r.URL.Path[7:] opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID")) if oerr != nil { jsonErrorReport(w, r, oerr.Error(), oerr.Status()) return } /* So, what are we doing? Depends on the HTTP method, of course */ switch r.Method { case "GET", "DELETE": if opUser.IsValidator() || !opUser.IsAdmin() && r.Method == "DELETE" && !(opUser.IsClient() && opUser.(*client.Client).NodeName == nodeName) { jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden) return } chefNode, nerr := node.Get(nodeName) if nerr != nil { jsonErrorReport(w, r, nerr.Error(), http.StatusNotFound) return } enc := json.NewEncoder(w) if err := enc.Encode(&chefNode); err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } if r.Method == "DELETE" { err := chefNode.Delete() if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } if lerr := loginfo.LogEvent(opUser, chefNode, "delete"); lerr != nil { jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError) return } } case "PUT": if !opUser.IsAdmin() && !(opUser.IsClient() && opUser.(*client.Client).NodeName == nodeName) { jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden) return } nodeData, jerr := parseObjJSON(r.Body) if jerr != nil { jsonErrorReport(w, r, jerr.Error(), http.StatusBadRequest) return } chefNode, kerr := node.Get(nodeName) if kerr != nil { jsonErrorReport(w, r, kerr.Error(), http.StatusNotFound) return } /* If nodeName and nodeData["name"] don't match, we * need to make a new node. Make sure that node doesn't * exist. */ if _, found := nodeData["name"]; !found { nodeData["name"] = nodeName } jsonName, sterr := util.ValidateAsString(nodeData["name"]) if sterr != nil { jsonErrorReport(w, r, sterr.Error(), http.StatusBadRequest) return } if nodeName != jsonName && jsonName != "" { jsonErrorReport(w, r, "Node name mismatch.", http.StatusBadRequest) return } if jsonName == "" { nodeData["name"] = nodeName } nerr := chefNode.UpdateFromJSON(nodeData) if nerr != nil { jsonErrorReport(w, r, nerr.Error(), nerr.Status()) return } err := chefNode.Save() if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } if lerr := loginfo.LogEvent(opUser, chefNode, "modify"); lerr != nil { jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError) return } enc := json.NewEncoder(w) if err = enc.Encode(&chefNode); err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) } default: jsonErrorReport(w, r, "Unrecognized method!", http.StatusMethodNotAllowed) } }