blob: 57bd4466188a48a12fddb0d96af65e2c9d0d45d2 [file] [log] [blame]
Sergio Slobodrianbe829272017-07-17 14:45:45 -04001package main // import "ciena.com/envoyd"
2
3import (
4 "os"
5 "os/exec"
6 "fmt"
7 "log"
8 "strconv"
9 "time"
10 "net"
11 "io/ioutil"
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -040012 "io"
Sergio Slobodrianbe829272017-07-17 14:45:45 -040013 "text/template"
14 "encoding/json"
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -040015 "sync"
16 "flag"
17 "bufio"
Sergio Slobodrianbe829272017-07-17 14:45:45 -040018 consulapi "github.com/hashicorp/consul/api"
19)
20
21// DATA STRUCTURES
22
Sergio Slobodrianbe829272017-07-17 14:45:45 -040023//Client provides an interface for getting data out of Consul
24type Client interface {
25// Get a Service from consulapi
26 Service(string, string) ([]string, error)
27// Register a service with local agent
28 Register(string, int) error
29// Deregister a service with local agent
30 DeRegister(string) error
31}
32
33type client struct {
34 consulapi *consulapi.Client
35}
36
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -040037type EnvoyConfigVars struct {
38 VolthaVip string
39 VolthaRR []string
40}
41
42type VolthaClusterEntry struct {
43 Prefix string
44 Id string
45 Host string
46}
47
Sergio Slobodrianbe829272017-07-17 14:45:45 -040048// This struct is not used yet
49// TODO: Update the daemon to use this structure to for a
50// more object oriented implementation
51type EnvoyControl struct {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -040052 // Command line parameters
53 assignmentKey string
54 envoyConfigTemplate string
55 envoyConfig string
56 vcoreSvcName string
57 consulSvcName string
58 vcorePort string
59 consulPort string
60 retries int
Sergio Slobodrianbe829272017-07-17 14:45:45 -040061 waitTime int
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -040062 // Runtime variables
63 consul * consulapi.Client
64 vcoreHostIpName string
65 vcoreIdName string
Sergio Slobodrianbe829272017-07-17 14:45:45 -040066 vc []VolthaClusterEntry
Sergio Slobodrianbe829272017-07-17 14:45:45 -040067 ipAddrs map[string][]string
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -040068 restartEpoch int
69 reLock sync.Mutex // Exclusive access to the restartEpoch
Sergio Slobodrianbe829272017-07-17 14:45:45 -040070}
71
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -040072
73func NewEnvoyControl() (ec * EnvoyControl) {
74 var envCtrl EnvoyControl = EnvoyControl { // Default values
75 // Command line parameters
76 assignmentKey: "service/voltha/data/core/assignment",
77 envoyConfigTemplate: "/envoy/voltha-grpc-proxy.template.json",
78 envoyConfig: "/envoy/voltha-grpc-proxy.json",
79 //envoyLogFile: "/envoy/voltha_access_log.log",
80 vcoreSvcName: "vcore",
81 consulSvcName: "consul",
82 vcorePort: "50556",
83 consulPort: "8500",
84 retries: 10,
85 waitTime: 2,
86 // Runtime variables
87 vcoreHostIpName: "host",
88 vcoreIdName: "id",
89 ipAddrs: make(map[string][]string),
90 restartEpoch: 0,
91 }
92 ec = &envCtrl
93 return
94}
95
96func (ec * EnvoyControl) resolveServiceAddress(serviceName string) (err error) {
97 for i := 0; i < ec.retries; i++ {
98 ec.ipAddrs[serviceName], err = net.LookupHost(serviceName)
99 if err != nil {
100 log.Printf("%s name resolution failed %d time(s) retrying...", serviceName, i+1)
101 } else {
102 //fmt.Printf("%s address = %s\n",serviceName, addrs[0])
103 break
104 }
105 time.Sleep(time.Duration(ec.waitTime) * time.Second)
106 }
107 if err != nil {
108 log.Printf("%s name resolution failed %d times gving up", serviceName, ec.retries)
109 }
110 return
111}
112
113func (ec * EnvoyControl) consulConnect(serviceName string, port string) (err error) {
114 // Fire up a consul client and get the kv store
115 cConfig := consulapi.DefaultNonPooledConfig()
116 cConfig.Address = ec.ipAddrs[serviceName][0] + ":" + port
117 ec.consul, err = consulapi.NewClient(cConfig)
118 if err != nil {
119 log.Fatal("error creating consul client aborting")
120 return
121 }
122 return
123}
124
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400125
126//NewConsul returns a Client interface for given consulapi address
127func NewConsulClient(addr string) (*client, error) {
128 config := consulapi.DefaultConfig()
129 config.Address = addr
130 c, err := consulapi.NewClient(config)
131 if err != nil {
132 return nil, err
133 }
134 return &client{consulapi: c}, nil
135}
136
137// Register a service with consulapi local agent
138func (c *client) Register(name string, port int) error {
139 reg := &consulapi.AgentServiceRegistration{
140 ID: name,
141 Name: name,
142 Port: port,
143 }
144 return c.consulapi.Agent().ServiceRegister(reg)
145}
146
147// DeRegister a service with consulapi local agent
148func (c *client) DeRegister(id string) error {
149 return c.consulapi.Agent().ServiceDeregister(id)
150}
151
152// Service return a service
153func (c *client) Service(service, tag string) ([]*consulapi.ServiceEntry, *consulapi.QueryMeta, error) {
154 passingOnly := true
155 addrs, meta, err := c.consulapi.Health().Service(service, tag, passingOnly, nil)
156 if len(addrs) == 0 && err == nil {
157 return nil, nil, fmt.Errorf("service ( %s ) was not found", service)
158 }
159 if err != nil {
160 return nil, nil, err
161 }
162 return addrs, meta, nil
163}
164
165// Starts envoy with the current restartEpoch
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400166func (ec * EnvoyControl) startEnvoy() {
167 var curEpoch int
168 var err error
169 var count int
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400170
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400171 ec.reLock.Lock() // Make sure we've got exclusive access to the variable
172 cmd := exec.Command("/usr/local/bin/envoy", "--restart-epoch", strconv.Itoa(ec.restartEpoch),
173 "--config-path", ec.envoyConfig, "--parent-shutdown-time-s", "10")
174
175 curEpoch = ec.restartEpoch
176 ec.restartEpoch += 1
177 ec.reLock.Unlock() // Done, release the lock.
178
179 stderr, err := cmd.StderrPipe()
180 if err != nil {
181 log.Printf("Couldn't attach to stderr running envoy command")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400182 panic(err)
183 }
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400184 stdout, err := cmd.StdoutPipe()
185 if err != nil {
186 log.Printf("Couldn't attach to stdout running envoy command")
187 panic(err)
188 }
189 so := bufio.NewReader(stdout)
190 se := bufio.NewReader(stderr)
191
192 if err = cmd.Start(); err != nil {
193 log.Fatal("Error starting envoy")
194 panic(err)
195 }
196 log.Printf("Envoy(%d) started", curEpoch)
197 soEof := false
198 seEof := false
199
200 data := make([]byte, 80)
201 log.Printf("Log forwarding for envoy(%d) started", curEpoch)
202 for {
203 data = make([]byte, 80)
204 count, err = so.Read(data)
205 log.Printf("ENVOY_LOG(%d): %s", curEpoch, string(data))
206 if err == io.EOF {
207 if seEof == true {
208 break
209 } else {
210 soEof = true
211 }
212 } else if err != nil {
213 log.Printf("Attempt to read envoy standard out failed")
214 panic(err)
215 } else if count > 0 {
216 log.Printf("ENVOY_LOG(%d)(%d): %s",curEpoch,count,string(data))
217 }
218 data = make([]byte, 80)
219 count, err = se.Read(data)
220 if err == io.EOF {
221 if soEof == true {
222 break
223 } else {
224 seEof = true
225 }
226 } else if err != nil {
227 log.Fatal("Attempt to read envoy standard err failed")
228 panic(err)
229 } else if count > 0 {
230 log.Printf("ENVOY_LOG(%d)(%d): %s",curEpoch,count,string(data))
231 }
232 }
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400233 log.Printf("Waiting on envoy %d to exit", curEpoch)
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400234 if err = cmd.Wait(); err != nil {
235 log.Printf("Envoy %d exited with an unexpected exit code", curEpoch)
236 panic(err)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400237 }
238 log.Printf("Envoy %d exited", curEpoch)
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400239 // Check if this was the primary envoy, if so
240 // something went terribly wrong, panic to force
241 // forcefully exit.
242 ec.reLock.Lock()
243 if ec.restartEpoch == (curEpoch + 1) {
244 ec.reLock.Unlock()
245 log.Fatal("Last running envoy exited, aborting!")
246 panic("This should never happen")
247 }
248 ec.reLock.Unlock()
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400249
250}
251
252// This function will use the provided templete file to generate
253// the targetfile substituting
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400254func (ec * EnvoyControl) updateEnvoyConfig(ecv * EnvoyConfigVars) (err error) {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400255 var firstRun bool = true
256 f := func() (bool) {
257 var rtrn bool = firstRun
258 firstRun = false
259 return rtrn
260 }
261 var funcs = template.FuncMap{"isFirst": f}
262 // Slurp up the template file.
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400263 tplt, err := ioutil.ReadFile(ec.envoyConfigTemplate)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400264 if err != nil {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400265 log.Fatal("ERROR reading the template file, aborting")
266 panic(err)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400267 }
268 //fmt.Println(string(tplt))
269 configTemplate, err := template.New("config").Funcs(funcs).Parse(string(tplt));
270 if err != nil {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400271 log.Fatal("Unexpected error loading the Envoy template, aborting")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400272 panic(err)
273 }
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400274 outFile,err := os.Create(ec.envoyConfig)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400275 if err != nil {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400276 log.Fatal("Unexpected error opening the Envoy config file for write, aborting")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400277 panic(err)
278 }
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400279 if err = configTemplate.Execute(outFile, ecv); err != nil {
280 log.Fatal("Unexpected error executing the Envoy config template, aborting")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400281 panic(err)
282 }
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400283 //cfgFile, err := ioutil.ReadFile(ec.envoyConfig)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400284 //if err != nil {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400285 // log.Fatal("ERROR reading the config file, aborting")
286 // panic(err)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400287 //}
288 //fmt.Println(string(cfgFile))
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400289 return
290}
291
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400292func (ec * EnvoyControl) parseAssignment(jsonString []byte) (vCluster []VolthaClusterEntry, err error) {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400293 var f interface{}
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400294 var vc VolthaClusterEntry
295 //var isErr bool
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400296
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400297 log.Printf("Parsing %s", string(jsonString))
298 //err = json.Unmarshal(jsonString, &f)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400299 err = json.Unmarshal(jsonString, &f)
300 if err != nil {
301 log.Fatal("Unable to parse json record %s", jsonString)
302 panic(err)
303 } else {
304 m := f.(map[string]interface{})
305 for k, v := range m {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400306 isErr := false
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400307 vc.Prefix = k
308 //log.Printf("Processing key %s\n", k)
309 switch vv := v.(type) {
310 case map[string]interface{}:
311 for i, u := range vv {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400312 //log.Printf("Processing key %sn", i)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400313 switch uu := u.(type) {
314 case string:
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400315 if i == ec.vcoreHostIpName {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400316 vc.Host = uu
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400317 } else if i == ec.vcoreIdName {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400318 vc.Id = uu
319 } else {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400320 log.Printf("WARNING: unexpected descriptor,%s", i)
321 isErr = true
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400322 }
323 default:
324 log.Printf("WARNING: unexpected type, ")
325 log.Println(i, u)
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400326 isErr = true
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400327 }
328 }
329 default:
330 log.Printf("WARNING: unexpected type, ")
331 log.Println(k, v)
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400332 isErr = true
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400333 }
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400334 if ! isErr {
335 vCluster = append(vCluster, vc)
336 }
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400337 }
338 }
339 log.Println("Parsing complete")
340 return
341}
342
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400343func (ec * EnvoyControl) prepareEnvoyConfig(kvp * consulapi.KVPair, ecv * EnvoyConfigVars) (err error) {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400344 var vCluster []VolthaClusterEntry
345
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400346 ecv.VolthaVip = ec.ipAddrs[ec.vcoreSvcName][0] + ":" + ec.vcorePort
347
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400348 // Extract all values from the KV record
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400349 // In the future, the values should all be compared to what we currently have
350 vCluster, err = ec.parseAssignment([]byte(kvp.Value))
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400351 if err == nil {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400352 ec.vc = vCluster // For future use to determine if there's been a real change
353 //templateValues["VolthaRR"] = []string{}
354 ecv.VolthaRR = []string{}
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400355 for i := range vCluster {
356 //log.Printf("Processing %s\n", vCluster[i].Host)
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400357 //templateValues["VolthaRR"] = append(templateValues["VolthaRR"].([]string), vCluster[i].Host)
358 ecv.VolthaRR = append(ecv.VolthaRR, vCluster[i].Host + ":" + ec.vcorePort)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400359 }
360 } else {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400361 log.Fatal("Couldn't parse the KV record %s", string(kvp.Value))
362 panic(err)
363 }
364 return
365}
366
367func (ec * EnvoyControl) runEnvoy(kvp * consulapi.KVPair) {
368 var err error
369 var ecv EnvoyConfigVars
370
371 if err = ec.prepareEnvoyConfig(kvp, &ecv); err != nil {
372 log.Fatal("Error preparing envoy config variables, aborting")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400373 panic(err)
374 }
375
376 // Now that we have the data loaded, update the envoy config and start envoy
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400377 ec.updateEnvoyConfig(&ecv)
378 go ec.startEnvoy()
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400379}
380
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400381func (ec * EnvoyControl) readConsulKey(key string, qo * consulapi.QueryOptions) (kvp * consulapi.KVPair, meta * consulapi.QueryMeta, err error) {
382
383 kv := ec.consul.KV()
384 // Get the initial values of the assignment key which contains individual
385 // voltha core IP addresses. This may be empty until voltha populates it
386 // so it must be checked
387 kvp, meta, err = kv.Get(ec.assignmentKey, qo)
388 for i := 0; i < ec.retries; i++ {
389 if err != nil {
390 fmt.Println(err)
391 log.Printf("Unable to read assignment consul key, retry %d", i+1)
392 time.Sleep(time.Duration(ec.waitTime) * time.Second)
393 kvp, meta, err = kv.Get(ec.assignmentKey, qo)
394 } else if kvp != nil && len(string(kvp.Value)) > 10 {
395 // A valid read, return
396 break
397 } else {
398 log.Printf("Voltha assignment key invalid, retry %d", i+1)
399 time.Sleep(time.Duration(ec.waitTime) * time.Second)
400 kvp, meta, err = kv.Get(ec.assignmentKey, qo)
401 }
402 if i == ec.retries {
403 log.Printf("Failed to read the assignment key after %d retries, aborting", ec.retries)
404 panic(err)
405 }
406 }
407 return
408}
409
410func (ec * EnvoyControl) runMonitorEnvoy() {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400411 var err error
412 var qo consulapi.QueryOptions
413
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400414 // Get the initial values of the assignment key which contains individual
415 // voltha core IP addresses. This may be empty until voltha populates it
416 // so it must be checked
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400417 kvp, meta, err := ec.readConsulKey(ec.assignmentKey, nil)
418 log.Printf("Starting Envoy")
419 ec.runEnvoy(kvp)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400420
421 for {
422 qo.WaitIndex = meta.LastIndex
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400423 qo.RequireConsistent = true
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400424 for {
425 if qo.WaitIndex != meta.LastIndex {
426 break
427 }
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400428 kvp, meta, err = ec.readConsulKey(ec.assignmentKey, &qo)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400429 if err != nil {
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400430 log.Printf("Unable to read assignment consul key")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400431 panic(err)
432 } else {
433 log.Println(string(kvp.Value))
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400434 log.Printf("meta.LastIndex = %d", meta.LastIndex)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400435 }
436 }
437 // Fell through, the index has changed thus the key has changed
438
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400439 log.Printf("Starting Envoy")
440 ec.runEnvoy(kvp)
441 log.Printf("meta.LastIndex = %d", meta.LastIndex)
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400442 }
443}
444
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400445func (ec * EnvoyControl) ParseCommandArguments() {
446 flag.StringVar(&(ec.assignmentKey), "assignment-key", ec.assignmentKey,
447 "The key for the voltha assignment value in consul")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400448
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400449 flag.StringVar(&( ec.envoyConfigTemplate),"envoy-cfg-template", ec.envoyConfigTemplate,
450 "The path to envoy's configuration template")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400451
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400452 flag.StringVar(&(ec.envoyConfig), "envoy-config", ec.envoyConfig,
453 "The path to envoy's configuration file" )
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400454
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400455 flag.StringVar(&(ec.vcoreSvcName), "vcore-svc-name", ec.vcoreSvcName,
456 "The service name of the voltha core service")
457
458 flag.StringVar(&(ec.consulSvcName),"consul-svc-nme", ec.consulSvcName,
459 "The service name of the consul service")
460
461 flag.StringVar(&(ec.vcorePort), "vcore-port", ec.vcorePort,
462 "The port where the vcore's GRPC service can be found")
463
464 flag.StringVar(&(ec.consulPort), "consul-port", ec.consulPort,
465 "The port where the consul service api can be found")
466
467 flag.IntVar(&(ec.retries), "retries", ec.retries,
468 "The number of times to retry name lookups and connect requests before failing")
469
470 flag.IntVar(&(ec.waitTime), "wait-time", ec.waitTime,
471 "The number of seconds to wait between retries")
472
473 flag.Parse()
474}
475
476func (ec * EnvoyControl) Initialize() (err error) {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400477 // Resolve consul's virtual ip address
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400478 if err = ec.resolveServiceAddress(ec.consulSvcName); err != nil {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400479 log.Fatal("Can't proceed without consul's vIP address")
480 panic(err)
481 }
482
483 // Resolve voltha's virtual ip address
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400484 if err = ec.resolveServiceAddress(ec.vcoreSvcName); err != nil {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400485 log.Fatal("Can't proceed without voltha's vIP address")
486 panic(err)
487 }
488
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400489 if err = ec.consulConnect(ec.consulSvcName, ec.consulPort); err != nil {
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400490 log.Fatal("error creating consul client aborting")
491 panic(err)
492 }
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400493
494 return
495}
496
497func main() {
498
499 var err error
500 var ec * EnvoyControl
501
502 ec = NewEnvoyControl()
503 ec.ParseCommandArguments()
504 if err = ec.Initialize(); err != nil {
505 log.Fatal("Envoy control initialization failed, aboring")
506 panic(err)
507 }
508
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400509
510 // Start envoy and monitor changes to the KV store to reload
511 // consul's config. This never returns unless somethign crashes.
Sergio Slobodrian8dec8de2017-07-20 12:45:07 -0400512 ec.runMonitorEnvoy()
513 log.Fatal("Monitor returned, this shouldn't happen")
Sergio Slobodrianbe829272017-07-17 14:45:45 -0400514}