This repository has been archived by the owner on Nov 26, 2017. It is now read-only.
/
main.go
149 lines (125 loc) · 3.08 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"log"
"os"
"time"
"github.com/codegangsta/cli"
"github.com/roboll/elector/backends"
"github.com/roboll/elector/elector"
"github.com/roboll/elector/handlers"
)
var release string
func main() {
app := cli.NewApp()
app.Name = "elector"
app.Usage = "elect a leader"
if release != "" {
app.Version = release
} else {
app.Version = "HEAD"
}
app.Flags = flags
app.Commands = commands
app.Run(os.Args)
}
var flags = []cli.Flag{
cli.StringFlag{
Name: "backend",
Usage: "backend name",
EnvVar: "ELECTOR_BACKEND",
},
cli.StringFlag{
Name: "instance-id",
Usage: "unique id, falls back to hostname",
EnvVar: "ELECTOR_INSTANCE_ID",
},
cli.StringFlag{
Name: "leader-start-command",
Usage: "leader start command - runs when state changes to LEADER",
EnvVar: "ELECTOR_START_COMMAND",
},
cli.StringFlag{
Name: "leader-end-command",
Usage: "leader end command - runs when state changes from LEADER",
EnvVar: "ELECTOR_STOP_COMMAND",
},
cli.StringFlag{
Name: "etcd-keyspace",
Usage: "etcd keyspace to elect on",
EnvVar: "ELECTOR_KEY",
},
cli.StringSliceFlag{
Name: "etcd-members",
Usage: "etcd members",
EnvVar: "ELECTOR_ETCD_MEMBERS",
},
}
var runFlags = []cli.Flag{
cli.DurationFlag{
Name: "error-timeout",
Usage: "error timeout - time to wait after an error before resuming candidacy",
EnvVar: "ELECTOR_ERROR_TIMEOUT",
},
}
var commands = []cli.Command{
{
Name: "run",
Description: "begin election",
Action: runWithArgs,
Flags: runFlags,
},
}
func runWithArgs(c *cli.Context) {
timeout := c.Duration("error-timeout")
if timeout == 0 {
log.Println("timeout not specified(or specied as 0); using default 30s")
timeout = 30 * time.Second
}
startCmd := c.GlobalString("leader-start-command")
if startCmd == "" {
log.Fatal("leader-start-command is required.")
}
endCmd := c.GlobalString("leader-end-command")
if endCmd == "" {
log.Fatal("leader-end-command is required.")
}
backendName := c.GlobalString("backend")
var backend elector.ElectionBackend
switch backendName {
case "etcd-lock":
keyspace := c.GlobalString("etcd-keyspace")
if keyspace == "" {
log.Fatal("keyspace is required.")
}
members := c.GlobalStringSlice("etcd-members")
if len(members) < 1 {
log.Fatal("at least one etcd-members is required.")
}
instanceID := c.GlobalString("instance-id")
caFile := c.GlobalString("ca-file")
certFile := c.GlobalString("cert-file")
keyFile := c.GlobalString("key-file")
backend = &backends.EtcdLock{
Members: &members,
Keyspace: &keyspace,
InstanceID: &instanceID,
CAFile: &caFile,
CertFile: &certFile,
KeyFile: &keyFile,
}
case "console":
backend = &backends.Console{}
default:
log.Fatal("must specify a valid backend.")
}
elector := &elector.Elector{
BeginLeaderHandler: handlers.CommandHandler(&startCmd),
EndLeaderHandler: handlers.CommandHandler(&endCmd),
ErrorHandler: handlers.TimeoutHandler(&timeout),
ElectionBackend: backend,
}
err := elector.Run()
if err != nil {
log.Fatal(err)
}
}