This commit is contained in:
mr 2024-09-16 16:59:12 +02:00
commit 754925c32c
10 changed files with 217 additions and 86 deletions

View File

@ -1,5 +1,61 @@
# oc-lib
oc-lib allows read/write/search operations into the main OpenCloud databases.
It also provides common initialization and configuration utilities for all OpenCloud components
## Usage example in a beego API
```go
const appname = "oc-mycomponent"
func main() {
// Init the oc-lib
oclib.Init(appname)
// Load the right config file
/* The configuration loader will load the configuration from the following sources:
* - the environment variables with the prefix OCAPPNAME_ - ex: OCMYCOMPONENT_MONGOURL
* - the file /etc/oc/appname.json - ex: /etc/oc/mycomponent.json
* - the file ./appname.json - ex: ./mycomponent.json
* The configuration loader will merge the configuration from the different sources
* The configuration loader will give priority to the environment variables
* The configuration loader will give priority to the local file over the default file
*/
o := oclib.GetConfLoader()
// init the local config object
models.GetConfig().Port = o.GetIntDefault("port", 8080)
models.GetConfig().LokiUrl = o.GetStringDefault("lokiurl", "")
models.GetConfig().LogLevel = o.GetStringDefault("loglevel", "info")
models.GetConfig().MongoUrl = o.GetStringDefault("mongourl", "mongodb://127.0.0.1:27017")
models.GetConfig().MongoDatabase = o.GetStringDefault("mongodatabase", "myDb")
models.GetConfig().NatsUrl = o.GetStringDefault("natsurl", "nats://localhost:4222")
models.GetConfig().mycomponentparam1 = o.GetStringDefault("mycomponentparam1", "mycomponentdefault1")
models.GetConfig().mycomponentparam2 = o.GetStringDefault("mycomponentparam2", "mycomponentdefault2")
// feed the library with the loaded config,
// this will also initialize a logger available via oclib.GetLogger()
oclib.SetConfig(
models.GetConfig().MongoUrl
models.GetConfig().MongoDatabase
models.GetConfig().NatsUrl
models.GetConfig().LokiUrl
models.GetConfig().LogLevel
)
// Beego init
beego.BConfig.AppName = appname
beego.BConfig.Listen.HTTPPort = models.GetConfig().Port
beego.BConfig.WebConfig.DirectoryIndex = true
beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
beego.Run()
}
```
## SPECIAL FLOWS IN OC-LIB RESUME :
### WORKFLOW AS ITS OWN WORKSPACE

19
config/app.go Normal file
View File

@ -0,0 +1,19 @@
package config
var appname string
// logs.CreateLogger
// Create a new logger
// Parameters:
// - appname: string : the name of the application using oclib
// - url: string : the url of a loki logger, console log only if ""
// Returns:
// - zerolog.Logger : the logger that will log for the library and the app
func SetAppName(name string) {
appname = name
}
func GetAppName() string {
return appname
}

View File

@ -1,4 +1,4 @@
package tools
package config
import "sync"
@ -14,6 +14,8 @@ type Config struct {
MongoDatabase string
Host string
Port string
LokiUrl string
LogLevel string
}
func (c Config) GetUrl() string {
@ -34,13 +36,20 @@ func GetConfig() *Config {
return instance
}
func SetConfig(url string, database string, natsUrl string) *Config {
once.Do(func() {
func SetConfig(mongoUrl string, database string, natsUrl string, lokiUrl string, logLevel string) *Config {
/*once.Do(func() {
instance = &Config{
MongoUrl: url,
MongoUrl: mongoUrl,
MongoDatabase: database,
NATSUrl: natsUrl,
LokiUrl: lokiUrl,
LogLevel: logLevel,
}
})
return instance
})*/
GetConfig().MongoUrl = mongoUrl
GetConfig().MongoDatabase = database
GetConfig().NATSUrl = natsUrl
GetConfig().LokiUrl = lokiUrl
GetConfig().LogLevel = logLevel
return GetConfig()
}

56
config/conf_loader.go Normal file
View File

@ -0,0 +1,56 @@
package config
import (
"os"
"strings"
"github.com/goraz/onion"
"github.com/rs/zerolog"
)
/* GetConfLoader
* Get the configuration loader for the application
* Parameters:
* - AppName: string : the name of the application
* Returns:
* - *onion.Onion : the configuration loader
* The configuration loader will load the configuration from the following sources:
* - the environment variables with the prefix APPNAME_
* - the file /etc/oc/appname.json
* - the file ./appname.json
* The configuration loader will merge the configuration from the different sources
* The configuration loader will give priority to the environment variables
* The configuration loader will give priority to the local file over the default file
*/
func GetConfLoader() *onion.Onion {
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
AppName := GetAppName()
EnvPrefix := strings.ToUpper(AppName[0:2]+AppName[3:]) + "_"
defaultConfigFile := "/etc/oc/" + AppName[3:] + ".json"
localConfigFile := "./" + AppName[3:] + ".json"
var configFile string
var o *onion.Onion
l3 := onion.NewEnvLayerPrefix("_", EnvPrefix)
l2, err := onion.NewFileLayer(localConfigFile, nil)
if err == nil {
logger.Info().Msg("Local config file found " + localConfigFile + ", overriding default file")
configFile = localConfigFile
}
l1, err := onion.NewFileLayer(defaultConfigFile, nil)
if err == nil {
logger.Info().Msg("Config file found : " + defaultConfigFile)
configFile = defaultConfigFile
}
if configFile == "" {
logger.Info().Msg("No config file found, using env")
o = onion.New(l3)
} else if l1 != nil && l2 != nil {
o = onion.New(l1, l2, l3)
} else if l1 == nil {
o = onion.New(l2, l3)
} else if l2 == nil {
o = onion.New(l1, l3)
}
return o
}

View File

@ -6,6 +6,7 @@ import (
"runtime/debug"
"cloud.o-forge.io/core/oc-lib/config"
"cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/dbs/mongo"
"cloud.o-forge.io/core/oc-lib/logs"
@ -24,6 +25,7 @@ import (
shared_workspace "cloud.o-forge.io/core/oc-lib/models/workspace/shared"
"cloud.o-forge.io/core/oc-lib/models/workspace/shared/rules/rule"
"cloud.o-forge.io/core/oc-lib/tools"
"github.com/goraz/onion"
"github.com/rs/zerolog"
)
@ -95,18 +97,42 @@ func AddPath(collection LibDataEnum, path string) {
paths[collection] = path
}
func Init(appName string, hostname string, port string) {
func Init(appName string) {
config.SetAppName(appName) // set the app name to the logger to define the main log chan
// create a temporary console logger for init
logs.SetLogger(logs.CreateLogger("main"))
}
//
// Expose subpackages
//
/* GetLogger returns the main logger
* @return zerolog.Logger
*/
func GetLogger() zerolog.Logger {
return logs.GetLogger()
}
/* SetConfig will set the config and create a logger according to app configuration and initialize mongo accessor
* @param url string
* @param database string
* @param natsUrl string
* @param lokiUrl string
* @param logLevel string
* @return *Config
*/
func SetConfig(mongoUrl string, database string, natsUrl string, lokiUrl string, logLevel string) *config.Config {
cfg := config.SetConfig(mongoUrl, database, natsUrl, lokiUrl, logLevel)
defer func() {
if r := recover(); r != nil {
tools.UncatchedError = append(tools.UncatchedError, errors.New("Panic recovered in Init : "+fmt.Sprintf("%v", r)+" - "+string(debug.Stack())))
fmt.Printf("Panic recovered in Init : %v - %v\n", r, string(debug.Stack()))
}
}()
logs.SetAppName(appName) // set the app name to the logger to define the main log chan
logs.SetLogger(logs.CreateLogger("main", "")) // create the logger
tools.GetConfig().Host = hostname // set the hostname to the config for inner discovery purpose actually not used
tools.GetConfig().Port = port // set the port to the config for inner discovery purpose actually not used
mongo.MONGOService.Init(models.GetModelsNames(), tools.GetConfig()) // init the mongo service
logs.CreateLogger("main")
mongo.MONGOService.Init(models.GetModelsNames(), config.GetConfig()) // init the mongo service
/*
Here we will check if the resource model is already stored in the database
If not we will store it
@ -143,11 +169,33 @@ func Init(appName string, hostname string, port string) {
})
}
}
return cfg
}
// GetLogger returns the main logger
func GetLogger() zerolog.Logger {
return logs.GetLogger()
/* GetConfig will get the config
* @return *Config
*/
func GetConfig() *config.Config {
return config.GetConfig()
}
/* GetConfLoader
* Get the configuration loader for the application
* Parameters:
* - AppName: string : the name of the application
* Returns:
* - *onion.Onion : the configuration loader
* The configuration loader will load the configuration from the following sources:
* - the environment variables with the prefix OCAPPNAME_
* - the file /etc/oc/appname.json
* - the file ./appname.json
* The configuration loader will merge the configuration from the different sources
* The configuration loader will give priority to the environment variables
* The configuration loader will give priority to the local file over the default file
*/
func GetConfLoader() *onion.Onion {
return config.GetConfLoader()
}
/*

View File

@ -5,11 +5,12 @@ import (
"runtime"
"time"
"cloud.o-forge.io/core/oc-lib/config"
"github.com/rs/zerolog"
)
var logger zerolog.Logger
var appname string
// logs.CreateLogger
// Create a new logger
// Parameters:
@ -18,14 +19,6 @@ var appname string
// Returns:
// - zerolog.Logger : the logger that will log for the library and the app
func SetAppName(name string) {
appname = name
}
func GetAppName() string {
return appname
}
func GetLogger() zerolog.Logger {
return logger
}
@ -34,10 +27,11 @@ func SetLogger(l zerolog.Logger) {
logger = l
}
func CreateLogger(funcName string, url string) zerolog.Logger {
func CreateLogger(funcName string) zerolog.Logger {
url := config.GetConfig().LokiUrl
if url != "" {
labels := map[string]string{
"app": appname,
"app": config.GetAppName(),
"code": "go",
"platform": runtime.GOOS,
"function": funcName,

View File

@ -82,9 +82,9 @@ func (dma *AbstractAccessor) GetCaller() *tools.HTTPCaller {
// Init initializes the accessor with the data type and the http caller
func (dma *AbstractAccessor) Init(t DataType, caller *tools.HTTPCaller) {
dma.Logger = logs.CreateLogger(t.String(), "") // Create a logger with the data type
dma.Caller = caller // Set the caller
dma.Type = t.String() // Set the data type
dma.Logger = logs.CreateLogger(t.String()) // Create a logger with the data type
dma.Caller = caller // Set the caller
dma.Type = t.String() // Set the data type
}
// GenericLoadOne loads one object from the database (generic)

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"cloud.o-forge.io/core/oc-lib/config"
"cloud.o-forge.io/core/oc-lib/dbs/mongo"
)
@ -51,11 +52,11 @@ type API struct{}
// GetState returns the state of the API
func (a *API) GetState() (State, int, error) {
// Check if the database is up
err := mongo.MONGOService.TestDB(GetConfig())
err := mongo.MONGOService.TestDB(config.GetConfig())
if err != nil {
return DB_FALLOUT, 200, err // If the database is not up, return database fallout
}
err = mongo.MONGOService.TestCollections(GetConfig(), []string{}) // Check if the collections are up
err = mongo.MONGOService.TestCollections(config.GetConfig(), []string{}) // Check if the collections are up
if err != nil {
return UNPROCESSABLE_ENTITY, 200, err // If the collections are not up, return unprocessable entity
}

View File

@ -1,53 +0,0 @@
package tools
import (
"strings"
"cloud.o-forge.io/core/oc-lib/logs"
"github.com/goraz/onion"
)
// GetConfLoader
// Get the configuration loader for the application
// Parameters:
// - AppName: string : the name of the application
// Returns:
// - *onion.Onion : the configuration loader
// The configuration loader will load the configuration from the following sources:
// - the environment variables with the prefix APPNAME_
// - the file /etc/oc/appname.json
// - the file ./appname.json
// The configuration loader will merge the configuration from the different sources
// The configuration loader will give priority to the environment variables
// The configuration loader will give priority to the local file over the default file
func GetConfLoader(AppName string) *onion.Onion {
logger := logs.GetLogger()
EnvPrefix := strings.ToUpper(AppName[0:2]+AppName[3:]) + "_"
defaultConfigFile := "/etc/oc/" + AppName[0:2] + ".json"
localConfigFile := "./" + AppName[0:2] + ".json"
var configFile string
var o *onion.Onion
l3 := onion.NewEnvLayerPrefix("_", EnvPrefix)
l2, err := onion.NewFileLayer(localConfigFile, nil)
if err == nil {
logger.Info().Msg("Local config file found " + localConfigFile + ", overriding default file")
configFile = localConfigFile
}
l1, err := onion.NewFileLayer(defaultConfigFile, nil)
if err == nil {
logger.Info().Msg("Config file found : " + defaultConfigFile)
configFile = defaultConfigFile
}
if configFile == "" {
logger.Info().Msg("No config file found, using env")
o = onion.New(l3)
} else if l1 != nil && l2 != nil {
o = onion.New(l1, l2, l3)
} else if l1 == nil {
o = onion.New(l2, l3)
} else if l2 == nil {
o = onion.New(l1, l3)
}
return o
}

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"strings"
"cloud.o-forge.io/core/oc-lib/config"
"github.com/nats-io/nats.go"
)
@ -44,10 +45,10 @@ func NewNATSCaller() *natsCaller {
// SetNATSPub sets a message to the NATS server
func (o *natsCaller) SetNATSPub(dataName string, method NATSMethod, data interface{}) string {
if GetConfig().NATSUrl == "" {
if config.GetConfig().NATSUrl == "" {
return " -> NATS_SERVER is not set"
}
nc, err := nats.Connect(GetConfig().NATSUrl)
nc, err := nats.Connect(config.GetConfig().NATSUrl)
if err != nil {
return " -> Could not reach NATS server : " + err.Error()
}