Skip to content

Commit

Permalink
feat (config) load service settings from config file.
Browse files Browse the repository at this point in the history
  • Loading branch information
pentateu committed Sep 18, 2019
1 parent 6401323 commit 2c7b358
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 7 deletions.
48 changes: 48 additions & 0 deletions broker/broker.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,23 @@ import (
log "github.com/sirupsen/logrus"
)

func mergeMaps(base, new map[string]interface{}) map[string]interface{} {
if base == nil {
base = map[string]interface{}{}
}
for key, value := range new {
base[key] = value
}
return base
}

func mergeConfigs(baseConfig moleculer.Config, userConfig []*moleculer.Config) moleculer.Config {
if len(userConfig) > 0 {
for _, config := range userConfig {
if config.Services != nil {
baseConfig.Services = mergeMaps(baseConfig.Services, config.Services)
}

if config.LogLevel != "" {
baseConfig.LogLevel = config.LogLevel
}
Expand Down Expand Up @@ -109,11 +123,45 @@ func (broker *ServiceBroker) stopService(svc *service.Service) {
broker.middlewares.CallHandlers("serviceStopped", svc)
}

// applyServiceConfig apply broker config to the service configuration
// settings is an import config copy from broker to the service.
func (broker *ServiceBroker) applyServiceConfig(svc *service.Service) {
if bkrConfig, exists := broker.config.Services[svc.Name()]; exists {
svcConfig, ok := bkrConfig.(map[string]interface{})
if ok {
_, ok := svcConfig["settings"]
if ok {
settings, ok := svcConfig["settings"].(map[string]interface{})
if ok {
svc.AddSettings(settings)
} else {
broker.logger.Error("Could not add service settings - Error converting the input settings to map[string]interface{} - Invalid format! Service Config : ", svcConfig)
}
}

_, ok = svcConfig["metadata"]
if ok {
metadata, ok := svcConfig["metadata"].(map[string]interface{})
if ok {
svc.AddSettings(metadata)
} else {
broker.logger.Error("Could not add service metadata - Error converting the input metadata to map[string]interface{} - Invalid format! Service Config : ", svcConfig)
}
}
} else {
broker.logger.Error("Could not apply service configuration - Error converting the service config to map[string]interface{} - Invalid format! Broker Config : ", bkrConfig)
}

}
}

// startService start a service.
func (broker *ServiceBroker) startService(svc *service.Service) {

broker.logger.Debug("Broker start service: ", svc.FullName())

broker.applyServiceConfig(svc)

broker.middlewares.CallHandlers("serviceStarting", svc)

broker.waitForDependencies(svc)
Expand Down
13 changes: 13 additions & 0 deletions cli/cli_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cli

import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestCli(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Cli Suite")
}
26 changes: 26 additions & 0 deletions cli/cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cli

import (
. "github.com/onsi/ginkgo"
)

var _ = Describe("Cli", func() {

Describe("Loading Configuration", func() {
It("shuold load config file and pass it on to the broker", func() {
// Start(
// &moleculer.Config{},
// func(broker *broker.ServiceBroker, cmd *cobra.Command) {
// broker.Publish(moleculer.ServiceSchema{
// Name: "user",
// Started: func(c moleculer.BrokerContext, svc moleculer.ServiceSchema) {
// Expect(svc.Settings["table"]).Should(Equal("userTable"))
// Expect(svc.Settings["idField"]).Should(Equal("id"))
// close(done)
// },
// })
// })
})
})

})
25 changes: 18 additions & 7 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"os"
"path"

"github.com/moleculer-go/moleculer"
"github.com/moleculer-go/moleculer/broker"
Expand Down Expand Up @@ -45,11 +46,19 @@ func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "c", "config file (default is <app>/.moleculer-config.yaml)")
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is <app>/.moleculer-config.yaml)")

// Cobra also supports local flags, which will only run
// when this action is called directly.
RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
// RootCmd.PersistentFlags().StringVar(&UserOpts.Config.LogLevel, "log", "l", "Log Level - fatal, error, debug, trace")
// viper.BindPFlag("log", RootCmd.PersistentFlags().Lookup("log"))

// RootCmd.PersistentFlags().StringVar(&UserOpts.Config.LogFormat, "logFormat", "lf", "Log Format - Options: JSON or TEXT")
// viper.BindPFlag("logFormat", RootCmd.PersistentFlags().Lookup("logFormat"))

// RootCmd.PersistentFlags().StringVar(&UserOpts.Config.Transporter, "transporter", "t", "Transporter")
// viper.BindPFlag("transporter", RootCmd.PersistentFlags().Lookup("transporter"))

// RootCmd.PersistentFlags().StringVar(&UserOpts.Config.Namespace, "namespace", "n", "Namespace")
// viper.BindPFlag("namespace", RootCmd.PersistentFlags().Lookup("namespace"))
}

// initConfig reads in config file and ENV variables if set.
Expand All @@ -64,15 +73,17 @@ func initConfig() {
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name ".moleculer-config" (without extension).
viper.AddConfigPath(basePath)
viper.SetConfigName(".moleculer-config")
viper.AddConfigPath(path.Dir(basePath))
viper.AddConfigPath(".")
viper.SetConfigName("moleculer-config")
}

viper.AutomaticEnv() // read in environment variables that match

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
} else {
fmt.Println("Error loading config - Error: ", err)
}
}
5 changes: 5 additions & 0 deletions cli/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/moleculer-go/moleculer"
"github.com/moleculer-go/moleculer/broker"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var environment string
Expand All @@ -25,6 +26,10 @@ var startCmd = &cobra.Command{
}

argsConfig := argsToConfig(cmd)
services := viper.GetStringMap("services")
if services != nil {
UserOpts.Config.Services = services
}
broker := broker.New(UserOpts.Config, argsConfig)

signalC := make(chan os.Signal)
Expand Down
10 changes: 10 additions & 0 deletions cli/test/test-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
log: error
transporter: NATS

services:
user:
table: userTable
idField: id
sink:
port: 8081

2 changes: 2 additions & 0 deletions moleculer.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ type Config struct {
Created func()
Started func()
Stopped func()

Services map[string]interface{}
}

var DefaultConfig = Config{
Expand Down
14 changes: 14 additions & 0 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,23 @@ func (service *Service) AddEventMap(eventInfo map[string]interface{}) *Event {
return &serviceEvent
}

//UpdateFromMap update the service metadata and settings from a serviceInfo map
func (service *Service) UpdateFromMap(serviceInfo map[string]interface{}) {
service.settings = serviceInfo["settings"].(map[string]interface{})
service.metadata = serviceInfo["metadata"].(map[string]interface{})
}

// AddSettings add settings to the service. it will be merged with the
// existing service settings
func (service *Service) AddSettings(settings map[string]interface{}) {
service.settings = MergeSettings(service.settings, settings)
}

// AddMetadata add metadata to the service. it will be merged with existing service metadata.
func (service *Service) AddMetadata(metadata map[string]interface{}) {
service.metadata = MergeSettings(service.metadata, metadata)
}

// populateFromMap populate a service with data from a map[string]interface{}.
func populateFromMap(service *Service, serviceInfo map[string]interface{}) {
if nodeID, ok := serviceInfo["nodeID"]; ok {
Expand Down Expand Up @@ -862,6 +874,8 @@ func CreateServiceFromMap(serviceInfo map[string]interface{}) *Service {
// Start called by the broker when the service is starting.
func (service *Service) Start(context moleculer.BrokerContext) {
if service.started != nil {
service.schema.Settings = service.settings
service.schema.Metadata = service.metadata
service.started(context, (*service.schema))
}
}
Expand Down

0 comments on commit 2c7b358

Please sign in to comment.