docker-icinga2/entrypoint/main.go
Alexander A. Klimov 1c187ee179 Ship msmtp
2021-03-01 17:17:29 +01:00

192 lines
4.3 KiB
Go

// Icinga 2 Docker image | (c) 2020 Icinga GmbH | GPLv2+
package main
import (
"bufio"
"fmt"
"github.com/otiai10/copy"
"golang.org/x/crypto/ssh/terminal"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"syscall"
"time"
)
const ca = "/var/lib/icinga2/certs/ca.crt"
const crtMode = 0640
const mSmtpRc = "/var/lib/icinga2/.msmtprc"
func main() {
if err := entrypoint(); err != nil {
logf(critical, "%s", err.Error())
os.Exit(1)
}
}
func entrypoint() error {
command := os.Args[1:]
if len(command) < 1 {
logf(warning, "Nothing to do.")
return nil
}
if os.Getpid() == 1 {
logf(info, "Initializing /data as we're the init process (PID 1)")
for _, dir := range []string{"etc", "var/cache", "var/lib", "var/log", "var/run", "var/spool"} {
dest := path.Join("/data", dir, "icinga2")
logf(info, "Checking %#v", dest)
if _, errSt := os.Stat(dest); errSt != nil {
if os.IsNotExist(errSt) {
src := path.Join("/data-init", dir, "icinga2")
logf(info, "Copying %#v to %#v", src, dest)
if errMA := os.MkdirAll(path.Dir(dest), 0755); errMA != nil {
return errMA
}
if errCp := copy.Copy(src, dest); errCp != nil {
return errCp
}
} else {
return errSt
}
}
}
logf(info, "Checking %#v", ca)
if _, errSt := os.Stat(ca); errSt != nil {
if os.IsNotExist(errSt) {
nodeSetup := []string{"node", "setup"}
runNodeSetup := false
for _, env := range os.Environ() {
if kv := strings.SplitN(env, "=", 2); len(kv) == 2 {
if strings.HasPrefix(kv[0], "ICINGA_") {
switch kv[0] = strings.ToLower(strings.TrimPrefix(kv[0], "ICINGA_")); kv[0] {
case "accept_commands", "accept_config", "disable_confd", "master":
runNodeSetup = true
if kv[1] == "1" {
nodeSetup = append(nodeSetup, "--"+strings.ReplaceAll(kv[0], "_", "-"))
}
case "cn", "endpoint", "global_zones", "listen",
"parent_host", "parent_zone", "ticket", "zone":
runNodeSetup = true
nodeSetup = append(nodeSetup, "--"+kv[0], kv[1])
case "trustedcert":
logf(info, "Writing trusted certificate")
runNodeSetup = true
dir, errTD := ioutil.TempDir("", "")
if errTD != nil {
return errTD
}
file := path.Join(dir, "trusted.crt")
if errWF := ioutil.WriteFile(file, []byte(kv[1]), crtMode); errWF != nil {
return errWF
}
nodeSetup = append(nodeSetup, "--"+kv[0], file)
case "cacert":
logf(info, "Writing CA certificate")
runNodeSetup = true
if errWF := ioutil.WriteFile(ca, []byte(kv[1]), crtMode); errWF != nil {
return errWF
}
}
}
}
}
if runNodeSetup {
logf(info, "Running 'node setup'")
cmd := exec.Command("icinga2", nodeSetup...)
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
if errRn := cmd.Run(); errRn != nil {
return errRn
}
}
} else {
return errSt
}
}
if mSmtpCfg, ok := os.LookupEnv("MSMTPRC"); ok {
logf(info, "Writing %#v", mSmtpRc)
if errWF := ioutil.WriteFile(mSmtpRc, []byte(mSmtpCfg), 0644); errWF != nil {
return errWF
}
}
command = append([]string{"dumb-init", "-c", "--"}, command...)
}
path := command[0]
if filepath.Base(path) == path {
logf(info, "Looking up %#v in $PATH", path)
abs, errLP := exec.LookPath(path)
if errLP != nil {
return errLP
}
path = abs
}
logf(info, "Running %#v", path)
return syscall.Exec(path, command, os.Environ())
}
type logSeverity uint8
const (
info logSeverity = iota
warning
critical
)
var out = bufio.NewWriter(os.Stderr)
var isTerminal = terminal.IsTerminal(int(os.Stderr.Fd()))
func logf(severity logSeverity, format string, a ...interface{}) {
var color, colorOff, seeverity string
switch severity {
case info:
color = "\x1b[32m"
seeverity = "information"
case warning:
color = "\x1b[33m\x1b[1m"
seeverity = "warning"
case critical:
color = "\x1b[31m\x1b[1m"
seeverity = "critical"
}
if isTerminal {
colorOff = "\x1b[0m"
} else {
color = ""
}
_, _ = fmt.Fprintf(out, "[%s] ", time.Now().Format("2006-01-02 15:04:05 -0700"))
_, _ = fmt.Fprintf(out, "%s%s%s/DockerEntrypoint: ", color, seeverity, colorOff)
_, _ = fmt.Fprintf(out, format, a...)
_, _ = fmt.Fprintln(out)
_ = out.Flush()
}