2022-04-05 16:38:25 +02:00
/ * *
* This file is part of VILLASweb - backend - go
2019-11-20 11:08:33 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-04-05 16:38:25 +02:00
2019-11-14 10:38:51 +01:00
package configuration
2019-11-13 20:31:06 +01:00
import (
"flag"
2021-04-21 14:16:23 +02:00
"fmt"
"io/ioutil"
2019-11-13 20:31:06 +01:00
"log"
"os"
2021-04-29 12:45:55 +02:00
"sort"
2021-02-04 17:49:53 +01:00
"strings"
2020-11-13 09:33:43 +01:00
2021-04-29 09:24:12 +02:00
"gopkg.in/yaml.v3"
2020-11-13 09:33:43 +01:00
"github.com/zpatrick/go-config"
2019-11-13 20:31:06 +01:00
)
// Global configuration
2021-01-25 10:57:25 +01:00
var GlobalConfig * config . Config = nil
2019-11-13 20:31:06 +01:00
2021-09-17 20:32:36 +02:00
type GroupedScenario struct {
Scenario int ` yaml:"scenario" `
Duplicate bool ` default:"false" yaml:"duplicate" `
}
var ScenarioGroupMap = map [ string ] [ ] GroupedScenario { }
2021-04-15 17:32:55 +02:00
2019-11-14 10:38:51 +01:00
func InitConfig ( ) error {
2021-01-25 10:57:25 +01:00
if GlobalConfig != nil {
2019-11-14 10:38:51 +01:00
return nil
2019-11-13 21:29:17 +01:00
}
2019-11-13 20:31:06 +01:00
var (
2021-02-04 20:04:29 +01:00
dbHost = flag . String ( "db-host" , "/var/run/postgresql" , "Host of the PostgreSQL database (default is /var/run/postgresql for localhost DB on Ubuntu systems)" )
2022-09-19 18:15:27 +02:00
dbPort = flag . Int ( "db-port" , - 1 , "Port of the PostgreSQL server" )
2021-02-04 20:04:29 +01:00
dbName = flag . String ( "db-name" , "villasdb" , "Name of the database to use (default is villasdb)" )
dbUser = flag . String ( "db-user" , "" , "Username of database connection (default is <empty>)" )
dbPass = flag . String ( "db-pass" , "" , "Password of database connection (default is <empty>)" )
dbSSLMode = flag . String ( "db-ssl-mode" , "disable" , "SSL mode of DB (default is disable)" ) // TODO: change default for production
2021-04-29 12:45:55 +02:00
dbClear = flag . Bool ( "db-clear" , false , "Set to true if you want to clear all DB tables upon startup. This parameter has to be used with great care, its effects cannot be reverted." )
2021-02-04 20:04:29 +01:00
amqpHost = flag . String ( "amqp-host" , "" , "If set, use this as host for AMQP broker (default is disabled)" )
amqpUser = flag . String ( "amqp-user" , "" , "Username for AMQP broker" )
amqpPass = flag . String ( "amqp-pass" , "" , "Password for AMQP broker" )
configFile = flag . String ( "config" , "" , "Path to YAML configuration file" )
port = flag . String ( "port" , "4000" , "Port of the backend (default is 4000)" )
adminUser = flag . String ( "admin-user" , "" , "Initial admin username" )
adminPass = flag . String ( "admin-pass" , "" , "Initial admin password" )
adminMail = flag . String ( "admin-mail" , "" , "Initial admin mail address" )
s3Bucket = flag . String ( "s3-bucket" , "" , "S3 Bucket for uploading files" )
s3Endpoint = flag . String ( "s3-endpoint" , "" , "Endpoint of S3 API for file uploads" )
2021-10-19 17:40:01 +02:00
s3EndpointPublic = flag . String ( "s3-endpoint-public" , "" , "Public endpoint address of S3 API for file uploads" )
2021-02-04 20:04:29 +01:00
s3Region = flag . String ( "s3-region" , "default" , "S3 Region for file uploads" )
s3NoSSL = flag . Bool ( "s3-nossl" , false , "Use encrypted connections to the S3 API" )
s3PathStyle = flag . Bool ( "s3-pathstyle" , false , "Use path-style S3 API" )
jwtSecret = flag . String ( "jwt-secret" , "This should NOT be here!!@33$8&" , "The JSON Web Token secret" )
jwtExpiresAfter = flag . String ( "jwt-expires-after" , "168h" /* 1 week */ , "The time after which the JSON Web Token expires" )
authExternal = flag . Bool ( "auth-external" , false , "Use external authentication via X-Forwarded-User header (e.g. OAuth2 Proxy)" )
2021-04-29 11:07:24 +02:00
authExternalLoginURL = flag . String ( "auth-external-login-url" , "/oauth2/start" , "A URL to initiate external login procedure" )
2021-02-04 20:04:29 +01:00
authExternalProviderName = flag . String ( "auth-external-provider-name" , "JupyterHub" , "A name of the external authentication provider" )
authLogoutURL = flag . String ( "auth-logout-url" , "/oauth2/sign_out?rd=https%3A%2F%2Fjupyter.k8s.eonerc.rwth-aachen.de%2Fhub%2Flogout" , "The URL to redirect the user to log out" )
title = flag . String ( "title" , "VILLASweb" , "Title shown in the frontend" )
subTitle = flag . String ( "sub-title" , "" , "Sub-title shown in the frontend" )
contactName = flag . String ( "contact-name" , "Steffen Vogel" , "Name of the administrative contact" )
contactMail = flag . String ( "contact-mail" , "svogel2@eonerc.rwth-aachen.de" , "EMail of the administrative contact" )
2021-04-29 12:45:55 +02:00
testDataPath = flag . String ( "test-data-path" , "" , "The path to a test data json file" )
2021-09-22 10:14:49 +02:00
groupsPath = flag . String ( "groups-path" , "" , "The path to a YAML file that maps user groups to scenario IDs" )
2021-05-21 13:08:24 +02:00
apiUpdateInterval = flag . String ( "api-update-interval" , "10s" /* 10 sec */ , "Interval in which API URL is queried for status updates of ICs" )
2021-10-19 19:04:10 +02:00
k8sRancherURL = flag . String ( "k8s-rancher-url" , "https://rancher.k8s.eonerc.rwth-aachen.de" , "URL of Rancher instance that is used to deploy the backend" )
k8sClusterName = flag . String ( "k8s-cluster-name" , "local" , "Name of the Kubernetes cluster where the backend is deployed" )
2022-01-10 10:47:34 +01:00
staleICTime = flag . String ( "stale-ic-time" , "1h" /* 1 hour */ , "Time after which an IC is considered stale" )
2022-04-20 16:45:33 +02:00
webRTCiceUrls = flag . String ( "webrtc-ice-urls" ,
"stun:stun.l.google.com:19302,villas:villas@stun:stun.0l.de,villas:villas@turn:turn.0l.de?transport=udp,villas:villas@turn:turn.0l.de?transport=tcp" ,
"WebRTC ICE URLs (comma-separated list, use username:password@url style for non-anonymous URLs)" )
2019-11-13 20:31:06 +01:00
)
flag . Parse ( )
static := map [ string ] string {
2021-02-04 20:04:29 +01:00
"db.host" : * dbHost ,
2022-09-19 18:15:27 +02:00
"db.port" : fmt . Sprint ( * dbPort ) ,
2021-02-04 20:04:29 +01:00
"db.name" : * dbName ,
"db.user" : * dbUser ,
"db.pass" : * dbPass ,
"db.ssl" : * dbSSLMode ,
"amqp.host" : * amqpHost ,
"amqp.user" : * amqpUser ,
"amqp.pass" : * amqpPass ,
"port" : * port ,
"admin.user" : * adminUser ,
"admin.pass" : * adminPass ,
"admin.mail" : * adminMail ,
"s3.bucket" : * s3Bucket ,
"s3.endpoint" : * s3Endpoint ,
2021-10-19 17:40:01 +02:00
"s3.endpoint-public" : * s3EndpointPublic ,
2021-02-04 20:04:29 +01:00
"s3.region" : * s3Region ,
"jwt.secret" : * jwtSecret ,
"jwt.expires-after" : * jwtExpiresAfter ,
2021-04-29 11:07:24 +02:00
"auth.external.login-url" : * authExternalLoginURL ,
2021-02-04 20:04:29 +01:00
"auth.external.provider-name" : * authExternalProviderName ,
"auth.logout-url" : * authLogoutURL ,
"title" : * title ,
"sub-title" : * subTitle ,
"contact.name" : * contactName ,
"contact.mail" : * contactMail ,
"test.datapath" : * testDataPath ,
2021-04-21 14:16:23 +02:00
"groups.path" : * groupsPath ,
2021-04-29 12:45:55 +02:00
"config.file" : * configFile ,
2021-05-21 13:08:24 +02:00
"apiupdateinterval" : * apiUpdateInterval ,
2021-10-19 19:04:10 +02:00
"k8s.rancher-url" : * k8sRancherURL ,
"k8s.cluster-name" : * k8sClusterName ,
2022-01-10 10:47:34 +01:00
"staleictime" : * staleICTime ,
2022-04-14 11:39:14 +02:00
"webrtc.ice-urls" : * webRTCiceUrls ,
2021-04-29 12:45:55 +02:00
}
2021-10-19 13:28:41 +02:00
if * dbClear {
2021-04-29 12:45:55 +02:00
static [ "db.clear" ] = "true"
} else {
static [ "db.clear" ] = "false"
2020-11-28 02:51:35 +01:00
}
2021-10-19 13:28:41 +02:00
if * s3NoSSL {
2020-11-28 02:51:35 +01:00
static [ "s3.nossl" ] = "true"
} else {
static [ "s3.nossl" ] = "false"
}
2021-10-19 13:28:41 +02:00
if * s3PathStyle {
2020-11-28 02:51:35 +01:00
static [ "s3.pathstyle" ] = "true"
} else {
static [ "s3.pathstyle" ] = "false"
2019-11-13 20:31:06 +01:00
}
2021-10-19 13:28:41 +02:00
if * authExternal {
2021-02-04 20:04:29 +01:00
static [ "auth.external.enabled" ] = "true"
2021-01-25 22:34:30 +01:00
} else {
2021-02-04 20:04:29 +01:00
static [ "auth.external.enabled" ] = "false"
2021-01-25 22:34:30 +01:00
}
2021-02-04 17:49:53 +01:00
mappings := map [ string ] string { }
2021-02-04 20:04:29 +01:00
for name := range static {
envName := strings . ReplaceAll ( name , "." , "_" )
envName = strings . ReplaceAll ( envName , "-" , "_" )
envName = strings . ToUpper ( envName )
2021-02-04 17:49:53 +01:00
mappings [ envName ] = name
2019-11-13 20:31:06 +01:00
}
defaults := config . NewStatic ( static )
env := config . NewEnvironment ( mappings )
2020-11-13 21:50:03 +01:00
if _ , err := os . Stat ( * configFile ) ; os . IsNotExist ( err ) {
2021-01-25 10:57:25 +01:00
GlobalConfig = config . NewConfig ( [ ] config . Provider { defaults , env } )
2020-11-13 21:50:03 +01:00
} else {
2019-11-13 20:31:06 +01:00
yamlFile := config . NewYAMLFile ( * configFile )
2021-01-25 10:57:25 +01:00
GlobalConfig = config . NewConfig ( [ ] config . Provider { defaults , yamlFile , env } )
2019-11-13 20:31:06 +01:00
}
2021-01-25 10:57:25 +01:00
err := GlobalConfig . Load ( )
2019-11-13 20:31:06 +01:00
if err != nil {
log . Fatal ( "failed to parse config" )
2019-11-14 10:38:51 +01:00
return err
2019-11-13 20:31:06 +01:00
}
2021-04-29 12:45:55 +02:00
settings , _ := GlobalConfig . Settings ( )
keys := make ( [ ] string , 0 , len ( settings ) )
for k := range settings {
keys = append ( keys , k )
2019-11-14 10:38:51 +01:00
}
2021-04-29 12:45:55 +02:00
sort . Strings ( keys )
2019-11-14 10:38:51 +01:00
2021-04-29 12:45:55 +02:00
log . Print ( "All settings (except for PW and secrets):" )
for _ , k := range keys {
if ! strings . Contains ( k , "pass" ) && ! strings . Contains ( k , "secret" ) {
log . Printf ( " %s = %s \n" , k , settings [ k ] )
2019-11-13 21:22:17 +01:00
}
2019-11-13 20:31:06 +01:00
}
2021-04-21 14:16:23 +02:00
return nil
}
2021-09-17 20:32:36 +02:00
func remove ( arr [ ] GroupedScenario , index int ) [ ] GroupedScenario {
arr [ index ] = arr [ len ( arr ) - 1 ]
return arr [ : len ( arr ) - 1 ]
}
2021-04-21 14:33:14 +02:00
func ReadGroupsFile ( path string ) error {
2021-04-21 14:16:23 +02:00
2021-04-22 14:56:02 +02:00
_ , err := os . Stat ( path )
2021-09-17 20:32:36 +02:00
if err != nil {
return err
}
2021-04-21 14:16:23 +02:00
2021-09-17 20:32:36 +02:00
yamlFile , err := os . Open ( path )
if err != nil {
return fmt . Errorf ( "error opening yaml file for groups: %v" , err )
}
log . Println ( "Successfully opened yaml groups file" , path )
2021-04-21 14:16:23 +02:00
2021-09-17 20:32:36 +02:00
defer yamlFile . Close ( )
2021-04-21 14:16:23 +02:00
2021-09-17 20:32:36 +02:00
byteValue , _ := ioutil . ReadAll ( yamlFile )
2021-04-21 14:16:23 +02:00
2021-09-17 20:32:36 +02:00
err = yaml . Unmarshal ( byteValue , & ScenarioGroupMap )
if err != nil {
return fmt . Errorf ( "error unmarshalling yaml into ScenarioGroupMap: %v" , err )
}
2021-04-21 14:16:23 +02:00
2021-09-17 20:32:36 +02:00
for _ , group := range ScenarioGroupMap {
for i , scenario := range group {
// remove invalid values that might have been introduced by typos
// (Unmarshal sets default values when it doesn't find a field)
if scenario . Scenario == 0 {
log . Println ( "Removing entry from ScenarioGroupMap, check for typos in the yaml!" )
remove ( group , i )
}
2021-04-22 14:56:02 +02:00
}
2021-09-17 20:32:36 +02:00
}
2021-04-22 14:56:02 +02:00
2021-09-17 20:32:36 +02:00
log . Println ( "ScenarioGroupMap" , ScenarioGroupMap )
2021-04-22 14:56:02 +02:00
2021-09-17 20:32:36 +02:00
return nil
2019-11-13 20:31:06 +01:00
}