package jobCheckin import ( "app/common" "encoding/json" client "github.com/influxdata/influxdb1-client/v2" "log" "net/http" "os" "regexp" "strings" ) type Job struct { Source string } // Validates the incomming request and writes an appropriate response. // 405: when not POST request // 401: when body is not given, or 'source' field missing // 500: failed to complete // 202: successfully complete func jobCheckinHandler(w http.ResponseWriter, r *http.Request) { log.Println("New request ===== ") if r.Method != "POST" { common.JsonRespond(&w, http.StatusMethodNotAllowed, "This end-point only accepts POST requests.") return } var j Job err := json.NewDecoder(r.Body).Decode(&j) if err != nil { common.JsonRespond(&w, http.StatusBadRequest, err.Error()) return } if j.Source == "" { common.JsonRespond(&w, http.StatusBadRequest, "no 'source' field in body. Try sending a json such as {'source': 'job_name'} in the body.") return } log.Println("source:", j.Source) measurement, err := chekinJob(j.Source) if err != nil { common.JsonRespond(&w, http.StatusInternalServerError, "Error while writing to Influx.") return } common.JsonRespond(&w, http.StatusAccepted, measurement) return } // Write job check-in to influx. func chekinJob(jobName string) (string, error) { jobNameClean, err := sanitizeJobName(jobName) if err != nil { return "", err } // Make client c, err := client.NewHTTPClient(client.HTTPConfig{ Addr: "http://" + os.Getenv("INFLUX_HOST") + ":" + os.Getenv("INFLUX_PORT"), }) if err != nil { return "", err } defer c.Close() // Create a new point batch bp, _ := client.NewBatchPoints(client.BatchPointsConfig{ Database: os.Getenv("INFLUX_DB"), Precision: "s", RetentionPolicy: os.Getenv("INFLUX_RP"), }) measurement := jobNameClean + "_checkins" // Create a point and add to batch tags := map[string]string{} fields := map[string]interface{}{"check-in": 1} pt, err := client.NewPoint(measurement, tags, fields) if err != nil { return "", err } bp.AddPoint(pt) // Write the batch err = c.Write(bp) if err != nil { return "", err } return measurement, nil } // Sanitize jobname - we only want letters, numbers, and underscores func sanitizeJobName(jobName string) (string, error) { // remove any non-alphanumeric chars, and non-space chars reg1, err := regexp.Compile("[^ _a-zA-Z0-9]+") if err != nil { return "", nil } jobName = reg1.ReplaceAllString(jobName, "") // replace spaces with _ reg2, err := regexp.Compile("[ ]+") if err != nil { return "", nil } jobName = reg2.ReplaceAllString(jobName, "_") return strings.ToLower(jobName), nil } // Every new endpoint/package MUST implement this function like so... func MakeHTTPHandler(endpoint string) http.Handler { return common.MakeHTTPHandler(endpoint, jobCheckinHandler) }