Improve configuration with config file

This adds explanations to the example config file, renames the file
in order to enable yaml syntax highlighting and fixes the parsing of
the flag specifying where to find the configuration file.
This commit is contained in:
Felix Auringer
2021-04-30 08:53:00 +02:00
committed by Jan-Eric Hellenberg
parent da38f56f64
commit c497e2f19c
4 changed files with 73 additions and 18 deletions

5
.gitignore vendored
View File

@ -1,8 +1,9 @@
# Project binary
poseidon
# Configuration file
configuration.yaml
# TLS certificate/key
*.crt
*.key
configuration.yaml

View File

@ -2,6 +2,7 @@ package config
import (
"crypto/tls"
"errors"
"flag"
"fmt"
"gitlab.hpi.de/codeocean/codemoon/poseidon/logging"
@ -13,6 +14,7 @@ import (
"strings"
)
// Config contains the default configuration of Poseidon.
var (
Config = &configuration{
Server: server{
@ -25,14 +27,16 @@ var (
},
Nomad: nomad{
Address: "",
Token: "",
Port: 4646,
Token: "",
TLS: false,
},
Logger: logger{
Level: "INFO",
},
}
configurationFilePath = "./configuration.yaml"
configurationInitialized = false
log = logging.GetLogger("config")
TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS13,
@ -41,6 +45,7 @@ var (
}
)
// server configures the Poseidon webserver.
type server struct {
Address string
Port int
@ -50,27 +55,39 @@ type server struct {
KeyFile string
}
// nomad configures the used Nomad cluster.
type nomad struct {
Address string
Token string
Port int
Token string
TLS bool
}
// logger configures the used logger.
type logger struct {
Level string
}
// configuration contains the complete configuration of Poseidon.
type configuration struct {
Server server
Nomad nomad
Logger logger
}
func InitConfig() {
// InitConfig merges configuration options from environment variables and
// a configuration file into the default configuration. Calls of InitConfig
// after the first call have no effect and return an error. InitConfig
// should be called directly after starting the program.
func InitConfig() error {
if configurationInitialized {
return errors.New("configuration is already initialized")
}
configurationInitialized = true
content := readConfigFile()
Config.mergeYaml(content)
Config.mergeEnvironmentVariables()
return nil
}
func (c *configuration) NomadAPIURL() *url.URL {
@ -93,16 +110,21 @@ func parseURL(address string, port int, tls bool) *url.URL {
}
func readConfigFile() []byte {
var configFilePath string
flag.StringVar(&configFilePath, "config", "./configuration.yaml", "path of the yaml config file")
flag.Parse()
data, err := os.ReadFile(configFilePath)
parseFlags()
data, err := os.ReadFile(configurationFilePath)
if err != nil {
log.WithError(err).Info("Using default configuration...")
}
return data
}
func parseFlags() {
if flag.Lookup("config") == nil {
flag.StringVar(&configurationFilePath, "config", configurationFilePath, "path of the yaml config file")
}
flag.Parse()
}
func (c *configuration) mergeYaml(content []byte) {
if err := yaml.Unmarshal(content, c); err != nil {
log.WithError(err).Fatal("Could not parse configuration file")
@ -114,20 +136,20 @@ func (c *configuration) mergeEnvironmentVariables() {
}
func readFromEnvironment(prefix string, value reflect.Value) {
if !value.CanSet() || !value.CanInterface() {
logEntry := log.WithField("prefix", prefix)
// if value was not derived from a pointer, it is not possible to alter its contents
if !value.CanSet() {
logEntry.Warn("Cannot overwrite struct field that can not be set")
return
}
if value.Kind() != reflect.Struct {
content, ok := os.LookupEnv(prefix)
logEntry := log.
WithField("prefix", prefix).
WithField("content", content)
if !ok {
return
}
logEntry = logEntry.WithField("content", content)
switch value.Kind() {
case reflect.String:
value.SetString(content)

View File

@ -0,0 +1,30 @@
# Configuration of the Poseidon webserver
server:
# Address on which the webserver listens
address: 127.0.0.1
# Port on which the webserver listens
port: 3000
# If set, this token is required in the X-Poseidon-Token header for each route except /health
token: SECRET
# If set, the API uses TLS for all incoming connections
tls: true
# The path to the certificate file used for TLS
certfile: ./poseidon.crt
# The path to the key file used for TLS
keyfile: ./poseidon.key
# Configuration of the used Nomad cluster
nomad:
# IP address / domain of the Nomad server
address: 127.0.0.1
# Port of the Nomad server
port: 4646
# Authenticate requests to the Nomad server with this token
token: SECRET
# Specifies whether to use TLS when communicating with the Nomad server
tls: false
# Configuration of the logger
logger:
# Log level that is used after reading the config (INFO until then)
level: DEBUG

View File

@ -63,7 +63,9 @@ func shutdownOnOSSignal(server *http.Server) {
}
func main() {
config.InitConfig()
if err := config.InitConfig(); err != nil {
log.WithError(err).Warn("Could not initialize configuration")
}
logging.InitializeLogging(config.Config.Logger.Level)
server := initServer()
log.WithField("address", server.Addr).Info("Starting server")