aboutsummaryrefslogtreecommitdiff
path: root/src/jobCheckin/jobCheckin.go
blob: 0a1dd1b14852e3d4702021da3203631555539339 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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)
}