Files
redoctober/redoctober.go
Daniel Dao d77eb9a456 move server code to an importable package
Commit 6f8424ad38
added an public function so we can import redoctober's NewServer
function in external test packages to create an RO server without having
to actually install the binary in test environments.

This used to work until 0f06d0a051,
which makes it impossible to import main package in external packages.

This change moves `NewServer` and its related code to a non-main
package so other packages can still import it in tests or any other
places.

Signed-off-by: Daniel Dao <dqminh89@gmail.com>
2017-06-21 10:31:22 -07:00

155 lines
4.4 KiB
Go

// Copyright (c) 2013 CloudFlare, Inc.
package main
import (
"flag"
"fmt"
"log"
"net"
"net/http"
"os"
"strings"
"github.com/cloudflare/redoctober/config"
"github.com/cloudflare/redoctober/core"
"github.com/cloudflare/redoctober/report"
"github.com/cloudflare/redoctober/server"
"github.com/prometheus/client_golang/prometheus"
)
// initPrometheus starts a goroutine with a Prometheus listener that
// listens on localhost:metricsPort. If the Prometheus handler can't
// be started, a log.Fatal call is made.
func initPrometheus() {
srv := &http.Server{
Addr: net.JoinHostPort(cfg.Metrics.Host, cfg.Metrics.Port),
Handler: prometheus.Handler(),
}
log.Printf("metrics.init start: addr=%s", srv.Addr)
go func() {
err := srv.ListenAndServe()
report.Check(err, nil)
log.Fatal(err.Error())
}()
}
const usage = `Usage:
redoctober -static <path> -vaultpath <path> -addr <addr> -certs <path1>[,<path2>,...] -keys <path1>[,<path2>,...] [-ca <path>]
single-cert example:
redoctober -vaultpath diskrecord.json -addr localhost:8080 -certs cert.pem -keys cert.key
multi-cert example:
redoctober -vaultpath diskrecord.json -addr localhost:8080 -certs cert1.pem,cert2.pem -keys cert1.key,cert2.key
`
var (
cfg, cli *config.Config
confFile string
vaultPath string
)
const (
defaultAddr = "localhost:8080"
defaultMetricsHost = "localhost"
defaultMetricsPort = "8081"
)
func init() {
// cli contains the configuration set by the command line
// options, and cfg is the actual Red October config.
cli = config.New()
cfg = config.New()
// customized the default index html with auto generated content
server.DefaultIndexHtml = indexHtml
cli.Server.Addr = defaultAddr
cli.Metrics.Host = defaultMetricsHost
cli.Metrics.Port = defaultMetricsPort
flag.Usage = func() {
fmt.Fprint(os.Stderr, "main usage dump\n")
fmt.Fprint(os.Stderr, usage)
flag.PrintDefaults()
os.Exit(2)
}
flag.StringVar(&confFile, "f", "", "path to config file")
flag.StringVar(&cli.Server.Addr, "addr", cli.Server.Addr,
"Server and port separated by :")
flag.StringVar(&cli.Server.CAPath, "ca", cli.Server.CAPath,
"Path of TLS CA for client authentication (optional)")
flag.StringVar(&cli.Server.CertPaths, "certs", cli.Server.CertPaths,
"Path(s) of TLS certificate in PEM format, comma-separated")
flag.StringVar(&cli.HipChat.Host, "hchost", cli.HipChat.Host,
"Hipchat Url Base (ex: hipchat.com)")
flag.StringVar(&cli.HipChat.APIKey, "hckey", cli.HipChat.APIKey,
"Hipchat API Key")
flag.StringVar(&cli.HipChat.Room, "hcroom", cli.HipChat.Room,
"Hipchat Room ID")
flag.StringVar(&cli.Server.KeyPaths, "keys", cli.Server.KeyPaths,
"Comma-separated list of PEM-encoded TLS private keys in the same order as certs")
flag.StringVar(&cli.Metrics.Host, "metrics-host", cli.Metrics.Host,
"The `host` the metrics endpoint should listen on.")
flag.StringVar(&cli.Metrics.Port, "metrics-port", cli.Metrics.Port,
"The `port` the metrics endpoint should listen on.")
flag.StringVar(&cli.UI.Root, "rohost", cli.UI.Root, "RedOctober URL Base (ex: localhost:8080)")
flag.StringVar(&cli.UI.Static, "static", cli.UI.Static,
"Path to override built-in index.html")
flag.BoolVar(&cli.Server.Systemd, "systemdfds", cli.Server.Systemd,
"Use systemd socket activation to listen on a file. Useful for binding privileged sockets.")
flag.StringVar(&vaultPath, "vaultpath", "diskrecord.json", "Path to the the disk vault")
flag.Parse()
}
//go:generate go run generate.go
func main() {
var err error
if confFile != "" {
cfg, err = config.Load(confFile)
if err != nil {
log.Fatal(err)
}
} else {
cfg = cli
}
report.Init(cfg)
if vaultPath == "" || !cfg.Valid() {
if !cfg.Valid() {
fmt.Fprintf(os.Stderr, "Invalid config.\n")
}
fmt.Fprint(os.Stderr, usage)
flag.PrintDefaults()
os.Exit(2)
}
if err := core.Init(vaultPath, cfg); err != nil {
report.Check(err, nil)
log.Fatal(err)
}
initPrometheus()
cpaths := strings.Split(cfg.Server.CertPaths, ",")
kpaths := strings.Split(cfg.Server.KeyPaths, ",")
s, l, err := server.NewServer(cfg.UI.Static, cfg.Server.Addr, cfg.Server.CAPath,
cpaths, kpaths, cfg.Server.Systemd)
if err != nil {
report.Check(err, nil)
log.Fatalf("Error starting redoctober server: %s\n", err)
}
log.Printf("http.serve start: addr=%s", cfg.Server.Addr)
report.Recover(func() {
err := s.Serve(l)
report.Check(err, nil)
log.Fatal(err.Error())
})
}