-
Notifications
You must be signed in to change notification settings - Fork 81
/
main.go
124 lines (98 loc) · 4.15 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
/*
Copyright (c) 2015 Andrey Sibiryov <[email protected]>
Copyright (c) 2015 Other contributors as noted in the AUTHORS file.
This file is part of GORB - Go Routing and Balancing.
GORB is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GORB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import (
"flag"
"net"
"net/http"
"os"
"github.com/kobolog/gorb/core"
"github.com/kobolog/gorb/util"
log "github.com/Sirupsen/logrus"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus/promhttp"
"strings"
)
var (
// Version get dynamically set to git rev by ldflags at build time
Version = "DEV"
debug = flag.Bool("v", false, "enable verbose output")
device = flag.String("i", "eth0", "default interface to bind services on")
flush = flag.Bool("f", false, "flush IPVS pools on start")
listen = flag.String("l", ":4672", "endpoint to listen for HTTP requests")
consul = flag.String("c", "", "URL for Consul HTTP API")
vipInterface = flag.String("vipi", "", "interface to add VIPs")
storeURLs = flag.String("store", "", "comma delimited list of store urls for sync data. All urls must have" +
" identical schemes and paths.")
storeTimeout = flag.Int64("store-sync-time", 60, "sync-time for store")
storeServicePath = flag.String("store-service-path", "services", "store service path")
storeBackendPath = flag.String("store-backend-path", "backends", "store backend path")
)
func main() {
// Called first to interrupt bootstrap and display usage if the user passed -h.
flag.Parse()
if *debug {
log.SetLevel(log.DebugLevel)
}
log.Info("starting GORB Daemon v" + Version)
if os.Geteuid() != 0 {
log.Fatalf("this program has to be run with root priveleges to access IPVS")
}
hostIPs, err := util.InterfaceIPs(*device)
if err != nil {
log.Fatalf("error while obtaining interface addresses: %s", err)
}
listenAddr, err := net.ResolveTCPAddr("tcp", *listen)
listenPort := uint16(0)
if err != nil {
log.Fatalf("error while obtaining listening port from '%s': %s", *listen, err)
} else {
listenPort = uint16(listenAddr.Port)
}
ctx, err := core.NewContext(core.ContextOptions{
Disco: *consul,
Endpoints: hostIPs,
Flush: *flush,
ListenPort: listenPort,
VipInterface: *vipInterface})
if err != nil {
log.Fatalf("error while initializing server context: %s", err)
}
// While it's not strictly required, close IPVS socket explicitly.
defer ctx.Close()
// sync with external store
if storeURLs != nil && len(*storeURLs) > 0 {
urls := strings.Split(*storeURLs, ",")
store, err := core.NewStore(urls, *storeServicePath, *storeBackendPath, *storeTimeout, ctx)
if err != nil {
log.Fatalf("error while initializing external store sync: %s", err)
}
defer store.Close()
}
core.RegisterPrometheusExporter(ctx)
r := mux.NewRouter()
r.Handle("/service/{vsID}", serviceCreateHandler{ctx}).Methods("PUT")
r.Handle("/service/{vsID}/{rsID}", backendCreateHandler{ctx}).Methods("PUT")
r.Handle("/service/{vsID}/{rsID}", backendUpdateHandler{ctx}).Methods("PATCH")
r.Handle("/service/{vsID}", serviceRemoveHandler{ctx}).Methods("DELETE")
r.Handle("/service/{vsID}/{rsID}", backendRemoveHandler{ctx}).Methods("DELETE")
r.Handle("/service", serviceListHandler{ctx}).Methods("GET")
r.Handle("/service/{vsID}", serviceStatusHandler{ctx}).Methods("GET")
r.Handle("/service/{vsID}/{rsID}", backendStatusHandler{ctx}).Methods("GET")
r.Handle("/metrics", promhttp.Handler()).Methods("GET")
log.Infof("setting up HTTP server on %s", *listen)
log.Fatal(http.ListenAndServe(*listen, r))
}