From f95d96acd8187eab9f72bddb60fb79cb7975231a Mon Sep 17 00:00:00 2001 From: Felix Auringer <48409110+felixauringer@users.noreply.github.com> Date: Wed, 28 Apr 2021 15:22:31 +0200 Subject: [PATCH] Add option to configure poseidon It exists a default configuration. It can be overwritten by adding a configuration.yaml. This can again be overwritten by environment variables. --- config/config.go | 116 ++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 3 +- main.go | 6 ++- nomad/api.tpl.nomad | 4 ++ 5 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 config/config.go diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..2c9370a --- /dev/null +++ b/config/config.go @@ -0,0 +1,116 @@ +package config + +import ( + "flag" + "fmt" + "gopkg.in/yaml.v3" + "log" + "os" + "reflect" + "strconv" + "strings" +) + +var ( + Config = &configuration{ + Server: server{ + Address: "127.0.0.1", + Port: 3000, + }, + Nomad: nomad{ + Address: "", + Token: "", + TLS: false, + }, + Logger: logger{ + Level: "INFO", + }, + } +) + +type server struct { + Address string + Port int +} + +type nomad struct { + Address string + Token string + TLS bool +} + +type logger struct { + Level string +} + +type configuration struct { + Server server + Nomad nomad + Logger logger +} + +func InitConfig() { + content := readConfigFile() + Config.mergeYaml(content) + Config.mergeEnvironmentVariables() +} + +func readConfigFile() []byte { + var configFilePath string + flag.StringVar(&configFilePath, "config", "./configuration.yaml", "path of the yaml config file") + data, err := os.ReadFile(configFilePath) + if err != nil { + log.Printf("Using default configuration... (%v)", err) + } + return data +} + +func (c *configuration) mergeYaml(content []byte) { + if err := yaml.Unmarshal(content, c); err != nil { + log.Fatalf("Could not parse configuration: %v", err) + } +} + +func (c *configuration) mergeEnvironmentVariables() { + readFromEnvironment("POSEIDON", reflect.ValueOf(c).Elem()) +} + +func readFromEnvironment(prefix string, value reflect.Value) { + if !value.CanSet() || !value.CanInterface() { + return + } + + if value.Kind() != reflect.Struct { + content, ok := os.LookupEnv(prefix) + if !ok { + return + } + switch value.Kind() { + case reflect.String: + value.SetString(content) + case reflect.Int: + integer, err := strconv.Atoi(content) + if err != nil { + log.Printf("Could not parse environment variable %s with value '%q' as integer", prefix, content) + return + } + value.SetInt(int64(integer)) + case reflect.Bool: + boolean, err := strconv.ParseBool(content) + if err != nil { + log.Printf("Could not parse environment variable %s with value '%q' as boolean", prefix, content) + return + } + value.SetBool(boolean) + default: + // ignore this field + log.Printf("Setting configuration options of type %s via environment variables is not supported", value.Type().Name()) + } + } else { + for i := 0; i < value.NumField(); i++ { + fieldName := value.Type().Field(i).Name + newPrefix := fmt.Sprintf("%s_%s", prefix, strings.ToUpper(fieldName)) + readFromEnvironment(newPrefix, value.Field(i)) + } + } +} diff --git a/go.mod b/go.mod index 6ec6c60..085a1c6 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,5 @@ go 1.16 require ( github.com/gorilla/mux v1.8.0 github.com/stretchr/testify v1.7.0 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) diff --git a/go.sum b/go.sum index 5f1152c..cdec086 100644 --- a/go.sum +++ b/go.sum @@ -9,5 +9,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 1b72006..c869bf6 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,9 @@ package main import ( "context" + "fmt" "gitlab.hpi.de/codeocean/codemoon/poseidon/api" + "gitlab.hpi.de/codeocean/codemoon/poseidon/config" "log" "net/http" "os" @@ -11,8 +13,10 @@ import ( ) func main() { + config.InitConfig() + server := &http.Server{ - Addr: "0.0.0.0:3000", + Addr: fmt.Sprintf("%s:%d", config.Config.Server.Address, config.Config.Server.Port), WriteTimeout: time.Second * 15, ReadTimeout: time.Second * 15, IdleTimeout: time.Second * 60, diff --git a/nomad/api.tpl.nomad b/nomad/api.tpl.nomad index 700a911..8375204 100644 --- a/nomad/api.tpl.nomad +++ b/nomad/api.tpl.nomad @@ -55,6 +55,10 @@ job "${NOMAD_SLUG}" { image = "${IMAGE_NAME_ENV}" } + env { + POSEIDON_SERVER_ADDRESS = "${POSEIDON_LISTEN_ADDRESS}" + } + resources { memory = "100" // 100 MB RAM cpu = "100" // 100 MHz