-
Notifications
You must be signed in to change notification settings - Fork 20
/
main.go
113 lines (106 loc) · 3.38 KB
/
main.go
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
// Distributive is a tool for running distributed health checks in server clusters.
// It was designed with Consul in mind, but is platform agnostic.
// The idea is that the checks are run locally, but executed by a central server
// that records and logs their output. This model distributes responsibility to
// each node, instead of one central server, and allows for more types of checks.
package main
import (
"os"
"github.com/CiscoCloud/distributive/checklists"
log "github.com/Sirupsen/logrus"
"github.com/mitchellh/panicwrap"
_ "github.com/CiscoCloud/distributive/checks"
)
var useCache bool // should remote checks be run from the cache when possible?
const Version = "v0.2.5"
const Name = "distributive"
// getChecklists returns a list of checklists based on the supplied sources
func getChecklists(file string, dir string, url string, stdin bool) (lsts []checklists.Checklist) {
parseError := func(src string, err error) {
if err != nil {
log.WithFields(log.Fields{
"origin": src,
"error": err,
}).Fatal("Couldn't parse checklist.")
}
}
msg := "Creating checklist(s)..."
switch {
// checklists from file are already tagged with their origin
// this applies to FromFile, FromDirectory, FromURL
case file != "":
log.WithFields(log.Fields{
"type": "file",
"path": file,
}).Info(msg)
chklst, err := checklists.FromFile(file)
parseError(file, err)
lsts = append(lsts, chklst)
case dir != "":
log.WithFields(log.Fields{
"type": "dir",
"path": dir,
}).Info(msg)
chklsts, err := checklists.FromDirectory(dir)
parseError(dir, err)
lsts = append(lsts, chklsts...)
case url != "":
log.WithFields(log.Fields{
"type": "url",
"path": url,
}).Info(msg)
chklst, err := checklists.FromURL(url, useCache)
parseError(url, err)
lsts = append(lsts, chklst)
case stdin == true:
log.WithFields(log.Fields{
"type": "url",
"path": url,
}).Info(msg)
checklist, err := checklists.FromStdin()
checklist.Origin = "stdin" // TODO put this in the method
parseError("stdin", err)
lsts = append(lsts, checklist)
default:
log.Fatal("Neither file, URL, directory, nor stdin specified. Try --help.")
}
return lsts
}
// main reads the command line flag -f, runs the Check specified in the YAML,
// and exits with the appropriate message and exit code.
func main() {
// Set up global panic handling
exitStatus, err := panicwrap.BasicWrap(panicHandler)
if err != nil {
reportURL := "https://github.com/mitchellh/panicwrap"
log.WithFields(log.Fields{
"err": err.Error(),
}).Fatal("Please report this error to " + reportURL)
}
// If exitStatus >= 0, then we're the parent process and the panicwrap
// re-executed ourselves and completed. Just exit with the proper status.
if exitStatus >= 0 {
os.Exit(exitStatus)
}
// Otherwise, exitStatus < 0 means we're the child. Continue executing as
// normal...
// Set up and parse flags
log.Debug("Parsing flags")
file, URL, directory, stdin := getFlags()
log.Debug("Validating flags")
validateFlags(file, URL, directory)
// add workers to workers, parameterLength
log.Debug("Running checklists")
exitCode := 0
for _, chklst := range getChecklists(file, directory, URL, stdin) {
anyFailed, report := chklst.MakeReport()
if anyFailed {
exitCode = 1
}
log.WithFields(log.Fields{
"checklist": chklst.Name,
"report": report,
}).Info("Report from checklist")
}
os.Exit(exitCode)
}