Skip to content
Snippets Groups Projects
Commit 3a48f4e3 authored by Andre Sterba's avatar Andre Sterba
Browse files

Use config package to handle all controller configurations

parent c0b8b690
No related branches found
No related tags found
7 merge requests!246Develop,!245Develop into Master,!244Master into develop2 into master,!219Draft: Testing,!214Test pipelines,!177Use config package to handle all controller configurations,!138Develop
...@@ -21,3 +21,6 @@ debug.test ...@@ -21,3 +21,6 @@ debug.test
# Binary # Binary
gosdn gosdn
# Storage
stores/
...@@ -5,11 +5,13 @@ import ( ...@@ -5,11 +5,13 @@ import (
"net" "net"
"os" "os"
"testing" "testing"
"time" "time"
cpb "code.fbi.h-da.de/danet/api/go/gosdn/core" cpb "code.fbi.h-da.de/danet/api/go/gosdn/core"
ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd" ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
tpb "code.fbi.h-da.de/danet/api/go/gosdn/transport" tpb "code.fbi.h-da.de/danet/api/go/gosdn/transport"
"code.fbi.h-da.de/danet/gosdn/config"
"code.fbi.h-da.de/danet/gosdn/mocks" "code.fbi.h-da.de/danet/gosdn/mocks"
nbi "code.fbi.h-da.de/danet/gosdn/northbound/server" nbi "code.fbi.h-da.de/danet/gosdn/northbound/server"
"code.fbi.h-da.de/danet/gosdn/nucleus" "code.fbi.h-da.de/danet/gosdn/nucleus"
...@@ -128,9 +130,7 @@ func TestMain(m *testing.M) { ...@@ -128,9 +130,7 @@ func TestMain(m *testing.M) {
} }
func bootstrapIntegrationTest() { func bootstrapIntegrationTest() {
if os.Getenv("GOSDN_LOG") == "nolog" { log.SetLevel(config.LogLevel)
log.SetLevel(log.PanicLevel)
}
addr := os.Getenv("GOSDN_TEST_ENDPOINT") addr := os.Getenv("GOSDN_TEST_ENDPOINT")
if addr != "" { if addr != "" {
......
...@@ -34,6 +34,7 @@ package cmd ...@@ -34,6 +34,7 @@ package cmd
import ( import (
"context" "context"
"os" "os"
"path/filepath"
"code.fbi.h-da.de/danet/gosdn" "code.fbi.h-da.de/danet/gosdn"
...@@ -80,16 +81,22 @@ func init() { ...@@ -80,16 +81,22 @@ func init() {
rootCmd.Flags().StringVar(&csbiOrchestrstor, "csbi-orchestrator", "localhost:55056", "csbi orchestrator address") rootCmd.Flags().StringVar(&csbiOrchestrstor, "csbi-orchestrator", "localhost:55056", "csbi orchestrator address")
} }
const (
configHome string = "./configs"
configName string = "gosdn"
configType string = "toml"
)
// initConfig reads in config file and ENV variables if set. // initConfig reads in config file and ENV variables if set.
func initConfig() { func initConfig() {
if cfgFile != "" { if cfgFile != "" {
// Use config file from the flag. // Use config file from the flag.
viper.SetConfigFile(cfgFile) viper.SetConfigFile(cfgFile)
} else { } else {
viper.AddConfigPath("./configs") viper.AddConfigPath(configHome)
viper.AddConfigPath("/usr/local/etc/gosdn/") viper.AddConfigPath("/usr/local/etc/gosdn/")
viper.SetConfigType("toml") viper.SetConfigType(configType)
viper.SetConfigName("gosdn") viper.SetConfigName(configName)
} }
viper.AutomaticEnv() // read in environment variables that match viper.AutomaticEnv() // read in environment variables that match
...@@ -97,6 +104,8 @@ func initConfig() { ...@@ -97,6 +104,8 @@ func initConfig() {
// If a config file is found, read it in. // If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil { if err := viper.ReadInConfig(); err == nil {
log.Debug("Using config file:", viper.ConfigFileUsed()) log.Debug("Using config file:", viper.ConfigFileUsed())
} else {
ensureViperConfigFileExists()
} }
viper.SetDefault("socket", ":55055") viper.SetDefault("socket", ":55055")
...@@ -118,3 +127,28 @@ func initConfig() { ...@@ -118,3 +127,28 @@ func initConfig() {
log.SetReportCaller(false) log.SetReportCaller(false)
} }
} }
func ensureFileSystemStoreExists(pathToStore string) error {
emptyString := []byte("")
err := os.WriteFile(pathToStore, emptyString, 0600)
if err != nil {
return err
}
return nil
}
func ensureViperConfigFileExists() {
// Viper will crash if you call 'WriteConfig()' and the file does
// not exists yet.
// Therefore we handle this case here.
// Inspired by //https://github.com/spf13/viper/issues/430#issuecomment-661945101
configPath := filepath.Join(configHome, configName+"."+configType)
if _, err := os.Stat(configPath); os.IsNotExist(err) {
err := ensureFileSystemStoreExists(configPath)
if err != nil {
panic(err)
}
}
}
package gosdn
import (
"github.com/google/uuid"
"github.com/spf13/viper"
)
// Config represents the nucleus configuration
type Config struct {
BasePndUUID uuid.UUID
BaseSouthBoundType int32
BaseSouthBoundUUID uuid.UUID
}
func getUUIDFromViper(viperKey string) (uuid.UUID, error) {
UUIDAsString := viper.GetString(viperKey)
if UUIDAsString == "" {
newUUID := uuid.New()
viper.Set(viperKey, newUUID.String())
viper.WriteConfig()
return newUUID, nil
}
parsedUUID, err := uuid.Parse(UUIDAsString)
if err != nil {
return uuid.Nil, err
}
return parsedUUID, nil
}
// InitializeConfig loads the configuration
func (c *Config) InitializeConfig() error {
var err error
basePNDUUIDKey := "basePNDUUID"
baseSouthBoundTypeKey := "baseSouthBoundType"
baseSouthBoundUUIDKey := "baseSouthBoundUUID"
basePNDUUID, err := getUUIDFromViper(basePNDUUIDKey)
if err != nil {
return err
}
c.BasePndUUID = basePNDUUID
baseSouthBoundUUID, err := getUUIDFromViper(baseSouthBoundUUIDKey)
if err != nil {
return err
}
c.BaseSouthBoundUUID = baseSouthBoundUUID
c.BaseSouthBoundType = viper.GetInt32("BaseSouthBoundType")
if c.BaseSouthBoundType != 0 {
viper.Set(baseSouthBoundTypeKey, 0)
viper.WriteConfig()
}
return nil
}
package config
import (
"os"
"time"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
const (
defaultTimeOutDuration10minutes = time.Minute * 10
basePNDUUIDKey = "basePNDUUID"
baseSouthBoundTypeKey = "baseSouthBoundType"
baseSouthBoundUUIDKey = "baseSouthBoundUUID"
changeTimeoutKey = "GOSDN_CHANGE_TIMEOUT"
)
// BasePndUUID is an uuid for the base PND
var BasePndUUID uuid.UUID
// BaseSouthBoundType is the type of the base SBI
var BaseSouthBoundType int32
// BaseSouthBoundUUID is an uuid for the base SBI
var BaseSouthBoundUUID uuid.UUID
// ChangeTimeout is the default timeout for a change
var ChangeTimeout time.Duration
// LogLevel ist the default log level
var LogLevel logrus.Level
// Init gets called on module import
func Init() {
InitializeConfig()
}
// InitializeConfig loads the configuration
func InitializeConfig() error {
var err error
basePNDUUIDFromViper, err := getUUIDFromViper(basePNDUUIDKey)
if err != nil {
return err
}
BasePndUUID = basePNDUUIDFromViper
baseSouthBoundUUIDFromViper, err := getUUIDFromViper(baseSouthBoundUUIDKey)
if err != nil {
return err
}
BaseSouthBoundUUID = baseSouthBoundUUIDFromViper
BaseSouthBoundType = viper.GetInt32(baseSouthBoundTypeKey)
if BaseSouthBoundType != 0 {
viper.Set(baseSouthBoundTypeKey, 0)
viper.WriteConfig()
}
err = setChangeTimeout()
if err != nil {
return err
}
setLogLevel()
return nil
}
func getUUIDFromViper(viperKey string) (uuid.UUID, error) {
UUIDAsString := viper.GetString(viperKey)
if UUIDAsString == "" {
newUUID := uuid.New()
viper.Set(viperKey, newUUID.String())
viper.WriteConfig()
return newUUID, nil
}
parsedUUID, err := uuid.Parse(UUIDAsString)
if err != nil {
return uuid.Nil, err
}
return parsedUUID, nil
}
func setChangeTimeout() error {
e := os.Getenv(changeTimeoutKey)
if e != "" {
changeTimeout, err := time.ParseDuration(e)
if err != nil {
log.Fatal(err)
}
ChangeTimeout = changeTimeout
} else {
ChangeTimeout = time.Minute * 10
}
return nil
}
func setLogLevel() {
if os.Getenv("GOSDN_LOG") == "nolog" {
LogLevel = logrus.PanicLevel
} else {
LogLevel = logrus.InfoLevel
}
}
package config
import (
"os"
"testing"
"time"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
func TestInit(t *testing.T) {
viper.SetConfigFile("./config_test.toml")
viper.Set("baseSouthBoundType", 0)
viper.Set("baseSouthBoundUUID", "bf8160d4-4659-4a1b-98fd-f409a04111eb")
viper.Set("basePNDUUID", "bf8160d4-4659-4a1b-98fd-f409a04111ec")
viper.Set("GOSDN_CHANGE_TIMEOUT", "10m")
}
func TestUseExistingConfig(t *testing.T) {
TestInit(t)
err := InitializeConfig()
if err != nil {
t.Error(err)
return
}
if BasePndUUID.String() != "bf8160d4-4659-4a1b-98fd-f409a04111ec" {
t.Fatalf("BasePndUUID.String() is not bf8160d4-4659-4a1b-98fd-f409a04111ec. got=%s",
BasePndUUID.String())
}
if BaseSouthBoundUUID.String() != "bf8160d4-4659-4a1b-98fd-f409a04111eb" {
t.Fatalf("BaseSouthBoundUUID.String() is not bf8160d4-4659-4a1b-98fd-f409a04111eb. got=%s",
BaseSouthBoundUUID.String())
}
if BaseSouthBoundType != 0 {
t.Fatalf("BaseSouthBoundType is not 0. got=%d",
BaseSouthBoundType)
}
testChangeTimeout, _ := time.ParseDuration("10m")
defaultChangeTimeout := defaultTimeOutDuration10minutes
if defaultChangeTimeout != testChangeTimeout {
t.Fatalf("ChangeTimeout is not 10ms. got=%v",
ChangeTimeout)
}
if os.Getenv("GOSDN_LOG") == "nolog" {
if LogLevel != logrus.PanicLevel {
t.Fatalf("LogLevel is not %v. got=%v",
logrus.PanicLevel, LogLevel)
}
} else {
if LogLevel != logrus.InfoLevel {
t.Fatalf("LogLevel is not %v. got=%v",
logrus.InfoLevel, LogLevel)
}
}
}
package gosdn
import (
"testing"
"github.com/spf13/viper"
)
func Test_Init(t *testing.T) {
viper.SetConfigFile("./config_test.toml")
viper.Set("baseSouthBoundType", 0)
viper.Set("baseSouthBoundUUID", "bf8160d4-4659-4a1b-98fd-f409a04111eb")
viper.Set("basePNDUUID", "bf8160d4-4659-4a1b-98fd-f409a04111ec")
}
func Test_UseExistingConfig(t *testing.T) {
Test_Init(t)
testConfig := Config{}
err := testConfig.InitializeConfig()
if err != nil {
t.Error(err)
return
}
if testConfig.BasePndUUID.String() != "bf8160d4-4659-4a1b-98fd-f409a04111ec" {
t.Fatalf("testConfig.BasePndUUID.String() is not bf8160d4-4659-4a1b-98fd-f409a04111ec. got=%s",
testConfig.BasePndUUID.String())
}
if testConfig.BaseSouthBoundUUID.String() != "bf8160d4-4659-4a1b-98fd-f409a04111eb" {
t.Fatalf("testConfig.BaseSouthBoundUUID.String() is not bf8160d4-4659-4a1b-98fd-f409a04111eb. got=%s",
testConfig.BaseSouthBoundUUID.String())
}
if testConfig.BaseSouthBoundType != 0 {
t.Fatalf("testConfig.BaseSouthBoundType is not 0. got=%d",
testConfig.BaseSouthBoundType)
}
}
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
cpb "code.fbi.h-da.de/danet/api/go/gosdn/csbi" cpb "code.fbi.h-da.de/danet/api/go/gosdn/csbi"
ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd" ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound" spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
"code.fbi.h-da.de/danet/gosdn/config"
"code.fbi.h-da.de/danet/gosdn/interfaces/southbound" "code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
nbi "code.fbi.h-da.de/danet/gosdn/northbound/server" nbi "code.fbi.h-da.de/danet/gosdn/northbound/server"
"code.fbi.h-da.de/danet/gosdn/store" "code.fbi.h-da.de/danet/gosdn/store"
...@@ -61,13 +62,12 @@ func initialize() error { ...@@ -61,13 +62,12 @@ func initialize() error {
startHttpServer() startHttpServer()
coreLock.Unlock() coreLock.Unlock()
config := Config{}
err := config.InitializeConfig() err := config.InitializeConfig()
if err != nil { if err != nil {
return err return err
} }
return createSouthboundInterfaces(config) return createSouthboundInterfaces()
} }
func startGrpc() error { func startGrpc() error {
...@@ -98,13 +98,13 @@ func startGrpc() error { ...@@ -98,13 +98,13 @@ func startGrpc() error {
} }
// createSouthboundInterfaces initializes the controller with its supported SBIs // createSouthboundInterfaces initializes the controller with its supported SBIs
func createSouthboundInterfaces(config Config) error { func createSouthboundInterfaces() error {
sbi := nucleus.NewSBI(spb.Type(config.BaseSouthBoundType), config.BaseSouthBoundUUID) sbi := nucleus.NewSBI(spb.Type(config.BaseSouthBoundType), config.BaseSouthBoundUUID)
return createPrincipalNetworkDomain(sbi, config) return createPrincipalNetworkDomain(sbi)
} }
// createPrincipalNetworkDomain initializes the controller with an initial PND // createPrincipalNetworkDomain initializes the controller with an initial PND
func createPrincipalNetworkDomain(s southbound.SouthboundInterface, config Config) error { func createPrincipalNetworkDomain(s southbound.SouthboundInterface) error {
pnd, err := nucleus.NewPND("base", "gosdn base pnd", config.BasePndUUID, s, c.csbiClient, callback) pnd, err := nucleus.NewPND("base", "gosdn base pnd", config.BasePndUUID, s, c.csbiClient, callback)
if err != nil { if err != nil {
return err return err
......
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"os" "os"
"testing" "testing"
"code.fbi.h-da.de/danet/gosdn/config"
"github.com/google/uuid" "github.com/google/uuid"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
...@@ -17,10 +19,8 @@ var cuid uuid.UUID ...@@ -17,10 +19,8 @@ var cuid uuid.UUID
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
log.SetReportCaller(true) log.SetReportCaller(true)
log.SetLevel(config.LogLevel)
if os.Getenv("GOSDN_LOG") == "nolog" {
log.SetLevel(log.PanicLevel)
}
readTestUUIDs() readTestUUIDs()
os.Exit(m.Run()) os.Exit(m.Run())
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"time" "time"
ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd" ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
"code.fbi.h-da.de/danet/gosdn/config"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/openconfig/ygot/exampleoc" "github.com/openconfig/ygot/exampleoc"
"github.com/openconfig/ygot/ygot" "github.com/openconfig/ygot/ygot"
...@@ -61,7 +62,7 @@ func TestChange_CommitRollback(t *testing.T) { ...@@ -61,7 +62,7 @@ func TestChange_CommitRollback(t *testing.T) {
if err := c.Commit(); (err != nil) != wantErr { if err := c.Commit(); (err != nil) != wantErr {
t.Errorf("Commit() error = %v, wantErr %v", err, wantErr) t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
} }
time.Sleep(time.Millisecond * 200) time.Sleep(config.ChangeTimeout)
}() }()
got := <-callback got := <-callback
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
...@@ -103,7 +104,7 @@ func TestChange_CommitRollbackError(t *testing.T) { ...@@ -103,7 +104,7 @@ func TestChange_CommitRollbackError(t *testing.T) {
if err := c.Commit(); (err != nil) != wantErr { if err := c.Commit(); (err != nil) != wantErr {
t.Errorf("Commit() error = %v, wantErr %v", err, wantErr) t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
} }
time.Sleep(time.Millisecond * 200) time.Sleep(config.ChangeTimeout)
}() }()
got := <-c.errChan got := <-c.errChan
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment