package main
import (
“log”
“os”
“path/filepath”
“syscall”
“github.com/fsnotify/fsnotify”
proc “github.com/shirou/gopsutil/process”
)
const (
nginxprocessname = “nginx”
defaultnginxconfpath = “/etc/nginx”
watchpathenvvarname = “watch_nginx_conf_path”
)
var stderrlogger = log.new(os.stderr, “error: “, log.lshortfile)
var stdoutlogger = log.new(os.stdout, “”, log.lshortfile)
func getmasternginxpid() (int, error) {
processes, processeserr := proc.processes()
if processeserr != nil {
return 0, processeserr
}
nginxprocesses := map[int32]int32{}
for _, process := range processes {
processname, processnameerr := process.name()
if processnameerr != nil {
return 0, processnameerr
}
if processname == nginxprocessname {
ppid, ppiderr := process.ppid()
if ppiderr != nil {
return 0, ppiderr
}
nginxprocesses[process.pid] = ppid
}
}
var masternginxpid int32
for pid, ppid := range nginxprocesses {
if ppid == 0 {
masternginxpid = pid
break
}
}
stdoutlogger.println(“found master nginx pid:”, masternginxpid)
return int(masternginxpid), nil
}
func signalnginxreload(pid int) error {
stdoutlogger.printf(“signaling master nginx process (pid: %d) -> sighup\n”, pid)
nginxprocess, nginxprocesserr := os.findprocess(pid)
if nginxprocesserr != nil {
return nginxprocesserr
}
return nginxprocess.signal(syscall.sighup)
}
func main() {
watcher, watchererr := fsnotify.newwatcher()
if watchererr != nil {
stderrlogger.fatal(watchererr)
}
defer watcher.close()
done := make(chan bool)
go func() {
for {
select {
case event, ok := <-watcher.events:
if !ok {
return
}
if event.op&fsnotify.create == fsnotify.create {
if filepath.base(event.name) == “..data” {
stdoutlogger.println(“config map updated”)
nginxpid, nginxpiderr := getmasternginxpid()
if nginxpiderr != nil {
stderrlogger.printf(“getting master nginx pid failed: %s”, nginxpiderr.error())
continue
}
if err := signalnginxreload(nginxpid); err != nil {
stderrlogger.printf(“signaling master nginx process failed: %s”, err)
}
}
}
case err, ok := <-watcher.errors:
if !ok {
return
}
stderrlogger.printf(“received watcher.error: %s”, err)
}
}
}()
pathtowatch, ok := os.lookupenv(watchpathenvvarname)
if !ok {
pathtowatch = defaultnginxconfpath
}
stdoutlogger.printf(“adding path: `%s` to watch\n”, pathtowatch)
if err := watcher.add(pathtowatch); err != nil {
stderrlogger.fatal(err)
}
<-done
}