Skip to content

Commit

Permalink
Add CLI-based system-ready state indicator
Browse files Browse the repository at this point in the history
This eliminates the need for artificial delays to make sure Asterisk is
up and ready.  We now leverage a `cli.conf` entry to set the system global
variable `ASTERISK_CONFIG_SYSTEM_READY` when Asterisk has completely
loaded.
  • Loading branch information
Ulexus committed Mar 30, 2020
1 parent 9580f0a commit 5e50677
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 19 deletions.
5 changes: 5 additions & 0 deletions defaults/cli.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[startup_commands]
dialplan set global ASTERISK_CONFIG_SYSTEM_READY 1

#include cli_custom.conf
#include cli.d/*.conf
Empty file added defaults/cli.d/keep.conf
Empty file.
Empty file added defaults/cli_custom.conf
Empty file.
46 changes: 27 additions & 19 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"archive/zip"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -170,18 +171,6 @@ func (s *Service) Run() error {

s.engine.FirstRenderComplete(true)

// Wait for Asterisk to come up before proceeding, so as to not interrupt
// normal Asterisk loading with a reload
if err := waitAsterisk(ariUsername, s.Secret); err != nil {
return errors.Wrap(err, "failed to wait for Asterisk to come up")
}

// pad Asterisk startup to wait for complete load
//
// FIXME: we need to figure out a canonical and proactive way to determine
// is Asterisk fully up
time.Sleep(time.Second)

for {
if err := <-renderChan; err != nil {
return errors.Wrap(err, "failure during watch")
Expand Down Expand Up @@ -295,27 +284,39 @@ func render(e *kubetemplate.Engine, customRoot string, exportRoot string) error
}

func waitAsterisk(username, secret string) error {
r, err := http.NewRequest("GET", "http://127.0.0.1:8088/ari/asterisk/ping", nil)
r, err := http.NewRequest("GET", "http://127.0.0.1:8088/ari/asterisk/variable?variable=ASTERISK_CONFIG_SYSTEM_READY", nil)
if err != nil {
return errors.Wrap(err, "failed to construct ping request")
}
r.Header.Set("Content-Type", "application/json")
r.SetBasicAuth(username, secret)

type response struct {
Value string `json:"value"`
}
resp := new(response)

for {
time.Sleep(time.Second / 2)

ret, err := http.DefaultClient.Do(r)
if err != nil {
time.Sleep(time.Second)
continue
}

if err := ret.Body.Close(); err != nil {
return errors.Wrap(err, "failed to close http response body")
if err = json.NewDecoder(ret.Body).Decode(resp); err != nil {
// failed to decode into resp format
log.Println("failed to decode Asterisk response:", err)
continue
}

if ret.StatusCode == http.StatusOK {
return nil
if resp.Value != "1" {
// not yet ready
continue
}

// System ready
log.Println("Asterisk ready")
return nil
}
}

Expand Down Expand Up @@ -437,6 +438,13 @@ func newReloader(ctx context.Context, username, secret, modules string) *reloade
}

func (r *reloader) run(ctx context.Context) {
// Wait for Asterisk to come up before proceeding, so as to not interrupt
// normal Asterisk loading with a reload
log.Println("Waiting for Asterisk to be ready...")
if err := waitAsterisk(r.username, r.secret); err != nil {
log.Fatalln("failed to wait for Asterisk to come up:", err)
}

for {
select {
case <-ctx.Done():
Expand Down

0 comments on commit 5e50677

Please sign in to comment.