diff --git a/README.md b/README.md index 82d01f7..05c6e78 100644 --- a/README.md +++ b/README.md @@ -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 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 + */ + 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 diff --git a/config/app.go b/config/app.go new file mode 100644 index 0000000..a660625 --- /dev/null +++ b/config/app.go @@ -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 +} diff --git a/tools/conf.go b/config/conf.go similarity index 75% rename from tools/conf.go rename to config/conf.go index c72a6f9..566c4a3 100644 --- a/tools/conf.go +++ b/config/conf.go @@ -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,12 +36,14 @@ func GetConfig() *Config { return instance } -func SetConfig(url string, database string, natsUrl string) *Config { +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 diff --git a/tools/conf_loader.go b/config/conf_loader.go similarity index 56% rename from tools/conf_loader.go rename to config/conf_loader.go index 78bf595..7ca533f 100644 --- a/tools/conf_loader.go +++ b/config/conf_loader.go @@ -1,29 +1,31 @@ -package tools +package config import ( + "os" "strings" - "cloud.o-forge.io/core/oc-lib/logs" "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 +/* 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 := logs.GetLogger() - AppName := logs.GetAppName() + logger := zerolog.New(os.Stdout).With().Timestamp().Logger() + AppName := GetAppName() EnvPrefix := strings.ToUpper(AppName[0:2]+AppName[3:]) + "_" defaultConfigFile := "/etc/oc/" + AppName[0:2] + ".json" localConfigFile := "./" + AppName[0:2] + ".json" diff --git a/entrypoint.go b/entrypoint.go index fe938fb..b463ed8 100644 --- a/entrypoint.go +++ b/entrypoint.go @@ -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,17 @@ func AddPath(collection LibDataEnum, path string) { paths[collection] = path } -func Init(appName string, hostname string, port string) { +func Init(appName string) { 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 + 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")) + 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 @@ -145,11 +146,49 @@ func Init(appName string, hostname string, port string) { } } -// GetLogger returns the main logger +// +// 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 +* @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 { + logs.CreateLogger("main") + return config.SetConfig(mongoUrl, database, natsUrl, lokiUrl, logLevel) +} + +/* 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 { + return config.GetConfLoader() +} + /* * Search will search for the data in the database * @param filters *dbs.Filters diff --git a/logs/logger.go b/logs/logger.go index 933e3b5..0ebcbac 100644 --- a/logs/logger.go +++ b/logs/logger.go @@ -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, diff --git a/models/utils/abstracts.go b/models/utils/abstracts.go index 35bf71c..2333665 100644 --- a/models/utils/abstracts.go +++ b/models/utils/abstracts.go @@ -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) diff --git a/tools/api.go b/tools/api.go index 3c0e20c..34ba1e9 100644 --- a/tools/api.go +++ b/tools/api.go @@ -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 } diff --git a/tools/nats_caller.go b/tools/nats_caller.go index 16806ef..d4aa7fc 100644 --- a/tools/nats_caller.go +++ b/tools/nats_caller.go @@ -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() }