mirror of
https://github.com/cloudflare/redoctober.git
synced 2026-01-03 03:35:43 +00:00
Add support for config files. (#151)
This commit is contained in:
159
config/config.go
Normal file
159
config/config.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setIfNotEmpty(a *string, b string) {
|
||||||
|
if b != "" {
|
||||||
|
*a = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server contains the configuration information required to start a
|
||||||
|
// redoctober server.
|
||||||
|
type Server struct {
|
||||||
|
// Addr contains the host:port that the server should listen
|
||||||
|
// on.
|
||||||
|
Addr string `json:"address"`
|
||||||
|
|
||||||
|
// CAPath contains the path to the TLS CA for client
|
||||||
|
// authentication. This is an optional field.
|
||||||
|
CAPath string `json:"ca_path,omitempty"`
|
||||||
|
|
||||||
|
// KeyPaths and CertPaths contains a list of paths to TLS key
|
||||||
|
// pairs that should be used to secure connections to the
|
||||||
|
// server.
|
||||||
|
KeyPaths []string `json:"private_keys"`
|
||||||
|
CertPaths []string `json:"certificates"`
|
||||||
|
|
||||||
|
// Systemd indicates whether systemd socket activation should
|
||||||
|
// be used instead of a normal port listener.
|
||||||
|
Systemd bool `json:"use_systemd,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge copies over non-empty string values from other into the
|
||||||
|
// current Server config.
|
||||||
|
func (s *Server) Merge(other *Server) {
|
||||||
|
setIfNotEmpty(&s.Addr, other.Addr)
|
||||||
|
setIfNotEmpty(&s.CAPath, other.CAPath)
|
||||||
|
|
||||||
|
if len(other.KeyPaths) != 0 {
|
||||||
|
s.KeyPaths = other.KeyPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(other.CertPaths) != 0 {
|
||||||
|
s.CertPaths = other.CertPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.Systemd {
|
||||||
|
s.Systemd = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI contains the configuration information for the WWW API.
|
||||||
|
type UI struct {
|
||||||
|
// Root contains the base URL for the UI.
|
||||||
|
Root string `json:"root"`
|
||||||
|
|
||||||
|
// Static is an optional path for overriding the built in HTML
|
||||||
|
// UI.
|
||||||
|
Static string `json:"static"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge copies over non-empty string values from other into the
|
||||||
|
// current UI config.
|
||||||
|
func (ui *UI) Merge(other *UI) {
|
||||||
|
setIfNotEmpty(&ui.Root, other.Root)
|
||||||
|
setIfNotEmpty(&ui.Static, other.Static)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HipChat contains the settings for Hipchat integration.
|
||||||
|
type HipChat struct {
|
||||||
|
Host string `json:"host"`
|
||||||
|
Room string `json:"room"`
|
||||||
|
APIKey string `json:"api_key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge copies over non-empty settings from other into the current
|
||||||
|
// HipChat config.
|
||||||
|
func (hc *HipChat) Merge(other *HipChat) {
|
||||||
|
setIfNotEmpty(&hc.Host, other.Host)
|
||||||
|
setIfNotEmpty(&hc.Room, other.Room)
|
||||||
|
setIfNotEmpty(&hc.APIKey, other.APIKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metrics contains the configuration for the Prometheus metrics
|
||||||
|
// collector.
|
||||||
|
type Metrics struct {
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port string `json:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge copies over non-empty settings from other into the current
|
||||||
|
// Metrics config.
|
||||||
|
func (m *Metrics) Merge(other *Metrics) {
|
||||||
|
setIfNotEmpty(&m.Host, other.Host)
|
||||||
|
setIfNotEmpty(&m.Port, other.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config contains all the configuration options for a redoctober
|
||||||
|
// instance.
|
||||||
|
type Config struct {
|
||||||
|
Server *Server `json:"server"`
|
||||||
|
UI *UI `json:"ui"`
|
||||||
|
HipChat *HipChat `json:"hipchat"`
|
||||||
|
Metrics *Metrics `json:"metrics"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge copies over the non-empty settings from other into the
|
||||||
|
// current Config.
|
||||||
|
func (c *Config) Merge(other *Config) {
|
||||||
|
c.Server.Merge(other.Server)
|
||||||
|
c.UI.Merge(other.UI)
|
||||||
|
c.HipChat.Merge(other.HipChat)
|
||||||
|
c.Metrics.Merge(other.Metrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid ensures that the config has enough data to start a Red
|
||||||
|
// October process.
|
||||||
|
func (c *Config) Valid() bool {
|
||||||
|
// The RedOctober API relies on TLS for security.
|
||||||
|
if len(c.Server.CertPaths) == 0 || len(c.Server.KeyPaths) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// The server needs some address to listen on.
|
||||||
|
if c.Server.Addr == "" && !c.Server.Systemd {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new, empty config.
|
||||||
|
func New() *Config {
|
||||||
|
return &Config{
|
||||||
|
Server: &Server{},
|
||||||
|
UI: &UI{},
|
||||||
|
HipChat: &HipChat{},
|
||||||
|
Metrics: &Metrics{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load reads a JSON-encoded config file from disk.
|
||||||
|
func Load(path string) (*Config, error) {
|
||||||
|
cfg := New()
|
||||||
|
in, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(in, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
237
config/config_test.go
Normal file
237
config/config_test.go
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func (s *Server) equal(other *Server) bool {
|
||||||
|
if s.Addr != other.Addr {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.CAPath != other.CAPath {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.KeyPaths) != len(other.KeyPaths) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.CertPaths) != len(other.KeyPaths) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range s.KeyPaths {
|
||||||
|
if s.KeyPaths[i] != other.KeyPaths[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range s.CertPaths {
|
||||||
|
if s.CertPaths[i] != other.CertPaths[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Systemd != other.Systemd {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ui *UI) equal(other *UI) bool {
|
||||||
|
if ui.Root != other.Root {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ui.Static != other.Static {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HipChat) equal(other *HipChat) bool {
|
||||||
|
if hc.Host != other.Host || hc.Room != other.Room || hc.APIKey != other.APIKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Metrics) equal(other *Metrics) bool {
|
||||||
|
return m.Host == other.Host && m.Port == other.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) equal(other *Config) bool {
|
||||||
|
if !c.Server.equal(other.Server) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.UI.equal(other.UI) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.HipChat.equal(other.HipChat) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.Metrics.equal(other.Metrics) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestEmptyEqual makes sure two empty configurations are equal.
|
||||||
|
func TestEmptyEqual(t *testing.T) {
|
||||||
|
a := New()
|
||||||
|
b := New()
|
||||||
|
|
||||||
|
if !a.equal(b) {
|
||||||
|
t.Fatal("empty configurations should be equivalent")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMergeEmpty verifies the behaviour where merging a config into
|
||||||
|
// an empty config results in the empty config becoming the same
|
||||||
|
// config as the config being merged.
|
||||||
|
func TestMergeEmpty(t *testing.T) {
|
||||||
|
empty := New()
|
||||||
|
testConfig := &Config{
|
||||||
|
Server: &Server{
|
||||||
|
Addr: "localhost:8080",
|
||||||
|
CAPath: "",
|
||||||
|
KeyPaths: []string{"testdata/server.key"},
|
||||||
|
CertPaths: []string{"testdata/server.pem"},
|
||||||
|
Systemd: true,
|
||||||
|
},
|
||||||
|
UI: &UI{
|
||||||
|
Root: "https://ro.example.net",
|
||||||
|
},
|
||||||
|
Metrics: &Metrics{
|
||||||
|
Host: "127.0.0.1",
|
||||||
|
Port: "8081",
|
||||||
|
},
|
||||||
|
HipChat: &HipChat{
|
||||||
|
Host: "hipchat.example.net",
|
||||||
|
Room: "redoctober",
|
||||||
|
APIKey: "i don't this key will work",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if empty.equal(testConfig) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
empty.Merge(testConfig)
|
||||||
|
if !empty.equal(testConfig) {
|
||||||
|
t.Fatal("merging should result in equivalent configs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMergeOverride verifies that merges will combine two configs.
|
||||||
|
func TestMergeOverride(t *testing.T) {
|
||||||
|
config := New()
|
||||||
|
config.Server = &Server{
|
||||||
|
Addr: "localhost:443",
|
||||||
|
CAPath: "",
|
||||||
|
KeyPaths: []string{"testdata/server.key"},
|
||||||
|
CertPaths: []string{"testdata/server.pem"},
|
||||||
|
}
|
||||||
|
|
||||||
|
merge := New()
|
||||||
|
merge.Server = &Server{
|
||||||
|
Addr: "localhost:8000",
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := New()
|
||||||
|
expected.Server = &Server{
|
||||||
|
Addr: "localhost:8000",
|
||||||
|
CAPath: "",
|
||||||
|
KeyPaths: []string{"testdata/server.key"},
|
||||||
|
CertPaths: []string{"testdata/server.pem"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.equal(merge) {
|
||||||
|
t.Fatal("configurations shouldn't match")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.equal(expected) {
|
||||||
|
t.Fatal("configurations shouldn't match")
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Merge(merge)
|
||||||
|
if !config.equal(expected) {
|
||||||
|
t.Fatal("configurations don't match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLoadFile validates loading a configuration from disk.
|
||||||
|
func TestLoadFile(t *testing.T) {
|
||||||
|
goodConfig := "testdata/config.json"
|
||||||
|
badConfig := "testdata/bad_config.json"
|
||||||
|
expected := New()
|
||||||
|
expected.Server = &Server{
|
||||||
|
Addr: "localhost:8080",
|
||||||
|
KeyPaths: []string{"testdata/server.key"},
|
||||||
|
CertPaths: []string{"testdata/server.pem"},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := Load("testdata/enoent.json")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("attempt to load non-existent file should fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = Load(badConfig)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("attempt to load malformed JSON should fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := Load(goodConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load config: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cfg.equal(expected) {
|
||||||
|
t.Fatal("loaded config is invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValid validates the Validate function.
|
||||||
|
func TestValid(t *testing.T) {
|
||||||
|
config := New()
|
||||||
|
|
||||||
|
if config.Valid() {
|
||||||
|
t.Fatal("empty config shouldn't be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Certs and no keys is an invalid config.
|
||||||
|
config.Server.CertPaths = []string{"testdata/server.pem"}
|
||||||
|
if config.Valid() {
|
||||||
|
t.Fatal("config shouldn't be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys and no certs is an invalid config.
|
||||||
|
config.Server.CertPaths = nil
|
||||||
|
config.Server.KeyPaths = []string{"testdata/server.key"}
|
||||||
|
if config.Valid() {
|
||||||
|
t.Fatal("config shouldn't be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key pairs but no address information is an invalid config.
|
||||||
|
config.Server.CertPaths = []string{"testdata/server.pem"}
|
||||||
|
if config.Valid() {
|
||||||
|
t.Fatal("config shouldn't be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Server.Addr = "localhost:8080"
|
||||||
|
if !config.Valid() {
|
||||||
|
t.Fatal("config should be valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Server.Addr = ""
|
||||||
|
config.Server.Systemd = true
|
||||||
|
if !config.Valid() {
|
||||||
|
t.Fatal("config should be valid")
|
||||||
|
}
|
||||||
|
}
|
||||||
8
config/testdata/bad_config.json
vendored
Normal file
8
config/testdata/bad_config.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"address": "localhost:8080",
|
||||||
|
"private_keys": ["testdata/server.key"],
|
||||||
|
"certificates": ["testdata/server.pem"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
12
config/testdata/config.json
vendored
Normal file
12
config/testdata/config.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"address": "localhost:8080",
|
||||||
|
"private_keys": [
|
||||||
|
"testdata/server.key"
|
||||||
|
],
|
||||||
|
"certificates": [
|
||||||
|
"testdata/server.pem"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/cloudflare/redoctober/config"
|
||||||
"github.com/cloudflare/redoctober/core"
|
"github.com/cloudflare/redoctober/core"
|
||||||
"github.com/coreos/go-systemd/activation"
|
"github.com/coreos/go-systemd/activation"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
@@ -209,7 +210,7 @@ func (this *indexHandler) handle(w http.ResponseWriter, r *http.Request) {
|
|||||||
// be started, a log.Fatal call is made.
|
// be started, a log.Fatal call is made.
|
||||||
func initPrometheus() {
|
func initPrometheus() {
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
Addr: net.JoinHostPort(metricsHost, metricsPort),
|
Addr: net.JoinHostPort(cfg.Metrics.Host, cfg.Metrics.Port),
|
||||||
Handler: prometheus.Handler(),
|
Handler: prometheus.Handler(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,22 +231,19 @@ redoctober -vaultpath diskrecord.json -addr localhost:8080 -certs cert1.pem,cert
|
|||||||
`
|
`
|
||||||
|
|
||||||
var (
|
var (
|
||||||
addr string
|
cfg, cli *config.Config
|
||||||
metricsHost string
|
confFile string
|
||||||
metricsPort string
|
vaultPath string
|
||||||
caPath string
|
|
||||||
certsPath string
|
|
||||||
hcHost string
|
|
||||||
hcKey string
|
|
||||||
hcRoom string
|
|
||||||
keysPath string
|
|
||||||
roHost string
|
|
||||||
staticPath string
|
|
||||||
useSystemdSocket bool
|
|
||||||
vaultPath string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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()
|
||||||
|
|
||||||
|
var certsPath, keysPath string
|
||||||
|
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprint(os.Stderr, "main usage dump\n")
|
fmt.Fprint(os.Stderr, "main usage dump\n")
|
||||||
fmt.Fprint(os.Stderr, usage)
|
fmt.Fprint(os.Stderr, usage)
|
||||||
@@ -253,46 +251,56 @@ func init() {
|
|||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.StringVar(&addr, "addr", "localhost:8080", "Server and port separated by :")
|
flag.StringVar(&confFile, "f", "", "path to config file")
|
||||||
flag.StringVar(&caPath, "ca", "", "Path of TLS CA for client authentication (optional)")
|
flag.StringVar(&cli.Server.Addr, "addr", "localhost:8080", "Server and port separated by :")
|
||||||
|
flag.StringVar(&cli.Server.CAPath, "ca", "", "Path of TLS CA for client authentication (optional)")
|
||||||
flag.StringVar(&certsPath, "certs", "", "Path(s) of TLS certificate in PEM format, comma-separated")
|
flag.StringVar(&certsPath, "certs", "", "Path(s) of TLS certificate in PEM format, comma-separated")
|
||||||
flag.StringVar(&hcHost, "hchost", "", "Hipchat Url Base (ex: hipchat.com)")
|
flag.StringVar(&cli.HipChat.Host, "hchost", "", "Hipchat Url Base (ex: hipchat.com)")
|
||||||
flag.StringVar(&hcKey, "hckey", "", "Hipchat API Key")
|
flag.StringVar(&cli.HipChat.APIKey, "hckey", "", "Hipchat API Key")
|
||||||
flag.StringVar(&hcRoom, "hcroom", "", "Hipchat Room Id")
|
flag.StringVar(&cli.HipChat.Room, "hcroom", "", "Hipchat Room Id")
|
||||||
flag.StringVar(&keysPath, "keys", "", "Path(s) of TLS private key in PEM format, comma-separated, must me in the same order as the certs")
|
flag.StringVar(&keysPath, "keys", "", "Path(s) of TLS private key in PEM format, comma-separated, must me in the same order as the certs")
|
||||||
flag.StringVar(&metricsHost, "metrics-host", "localhost", "The `host` the metrics endpoint should listen on.")
|
flag.StringVar(&cli.Metrics.Host, "metrics-host", "localhost", "The `host` the metrics endpoint should listen on.")
|
||||||
flag.StringVar(&metricsPort, "metrics-port", "8081", "The `port` the metrics endpoint should listen on.")
|
flag.StringVar(&cli.Metrics.Port, "metrics-port", "8081", "The `port` the metrics endpoint should listen on.")
|
||||||
flag.StringVar(&roHost, "rohost", "", "RedOctober Url Base (ex: localhost:8080)")
|
flag.StringVar(&cli.UI.Root, "rohost", "", "RedOctober Url Base (ex: localhost:8080)")
|
||||||
flag.StringVar(&staticPath, "static", "", "Path to override built-in index.html")
|
flag.StringVar(&cli.UI.Static, "static", "", "Path to override built-in index.html")
|
||||||
flag.BoolVar(&useSystemdSocket, "systemdfds", false, "Use systemd socket activation to listen on a file. Useful for binding privileged sockets.")
|
flag.BoolVar(&cli.Server.Systemd, "systemdfds", false, "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.StringVar(&vaultPath, "vaultpath", "diskrecord.json", "Path to the the disk vault")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
cli.Server.CertPaths = strings.Split(certsPath, ",")
|
||||||
|
cli.Server.KeyPaths = strings.Split(keysPath, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run generate.go
|
//go:generate go run generate.go
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if vaultPath == "" || certsPath == "" || keysPath == "" ||
|
var err error
|
||||||
(addr == "" && useSystemdSocket == false) {
|
if confFile != "" {
|
||||||
|
cfg, err = config.Load(confFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cfg.Merge(cli)
|
||||||
|
|
||||||
|
if vaultPath == "" || !cfg.Valid() {
|
||||||
fmt.Fprint(os.Stderr, usage)
|
fmt.Fprint(os.Stderr, usage)
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
certPaths := strings.Split(certsPath, ",")
|
if err := core.Init(vaultPath, cfg.HipChat.APIKey, cfg.HipChat.Room, cfg.HipChat.Room, cfg.UI.Root); err != nil {
|
||||||
keyPaths := strings.Split(keysPath, ",")
|
|
||||||
|
|
||||||
if err := core.Init(vaultPath, hcKey, hcRoom, hcHost, roHost); err != nil {
|
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
initPrometheus()
|
initPrometheus()
|
||||||
s, l, err := NewServer(staticPath, addr, caPath, certPaths, keyPaths, useSystemdSocket)
|
s, l, err := NewServer(cfg.UI.Static, cfg.Server.Addr, cfg.Server.CAPath,
|
||||||
|
cfg.Server.CertPaths, cfg.Server.KeyPaths, cfg.Server.Systemd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error starting redoctober server: %s\n", err)
|
log.Fatalf("Error starting redoctober server: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("http.serve start: addr=%s", addr)
|
log.Printf("http.serve start: addr=%s", cfg.Server.Addr)
|
||||||
log.Fatal(s.Serve(l))
|
log.Fatal(s.Serve(l))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user