Skip to content

Commit

Permalink
yyyar#29 Refactored code to support multiple config locations; Added …
Browse files Browse the repository at this point in the history
…better arguments parsing; Added file and basic Consul config pullers
  • Loading branch information
yyyar committed Jul 30, 2016
1 parent 648da5d commit f9c89f5
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 45 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ deps: clean-deps
github.com/elgs/gojq \
github.com/gin-gonic/gin \
github.com/hashicorp/consul/api \
github.com/spf13/cobra \
github.com/laher/goxc

clean-dist:
Expand Down
16 changes: 16 additions & 0 deletions config/gobetween.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"servers": {
"sample":{
"bind":"localhost:3000",
"healthcheck": {
"kind": "ping",
"interval": "2s",
"timeout": "1s"
},
"discovery": {
"kind": "static",
"static_list": ["localhost:8000 weight=1"]
}
}
}
}
11 changes: 5 additions & 6 deletions src/api/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@ func attachRoot(app *gin.RouterGroup) {
app.GET("/", func(c *gin.Context) {

c.IndentedJSON(http.StatusOK, gin.H{
"pid": os.Getpid(),
"time": time.Now(),
"startTime": info.StartTime,
"uptime": time.Now().Sub(info.StartTime).String(),
"version": info.Version,
"configPath": info.ConfigPath,
"pid": os.Getpid(),
"time": time.Now(),
"startTime": info.StartTime,
"uptime": time.Now().Sub(info.StartTime).String(),
"version": info.Version,
})
})

Expand Down
23 changes: 23 additions & 0 deletions src/cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* cmd.go - command line runner
*
* @author Yaroslav Pogrebnyak <[email protected]>
*/
package cmd

import (
"../config"
)

/**
* App Start function to call after initialization
*/
var start func(*config.Config)

/**
* Execute processing flags
*/
func Execute(f func(*config.Config)) {
start = f
RootCmd.Execute()
}
63 changes: 63 additions & 0 deletions src/cmd/from-consul.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* from-consul.go - pull config from consul and run
*
* @author Yaroslav Pogrebnyak <[email protected]>
*/
package cmd

import (
"../config"
"../utils/codec"
consul "github.com/hashicorp/consul/api"
"github.com/spf13/cobra"
"log"
)

/* Parsed options */
var consulHost string
var consulKey string

/**
* Add command
*/
func init() {

FromConsulCmd.Flags().StringVarP(&consulHost, "host", "", "localhost", "Consul host")
FromConsulCmd.Flags().StringVarP(&consulKey, "key", "", "gobetween", "Consul Key to pull config from")

RootCmd.AddCommand(FromConsulCmd)
}

/**
* FromConsul command
*/
var FromConsulCmd = &cobra.Command{
Use: "from-consul",
Short: "Pull config from Consul",
Long: `Pull config from the Consul Key-Value storage`,
Run: func(cmd *cobra.Command, args []string) {

client, err := consul.NewClient(&consul.Config{
Address: consulHost,
})
if err != nil {
log.Fatal(err)
}

pair, _, err := client.KV().Get(consulKey, nil)
if err != nil {
log.Fatal(err)
}

if pair == nil {
log.Fatal("Empty value for key " + consulKey)
}

var cfg config.Config
if err := codec.Decode(string(pair.Value), &cfg, format); err != nil {
log.Fatal(err)
}

start(&cfg)
},
}
47 changes: 47 additions & 0 deletions src/cmd/from-file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* from-file.go - pull config from file and run
*
* @author Yaroslav Pogrebnyak <[email protected]>
*/
package cmd

import (
"../config"
"../utils/codec"
"github.com/spf13/cobra"
"io/ioutil"
"log"
)

/* Parsed options */
var configPath string

/**
* Add Root Command
*/
func init() {
FromFileCmd.Flags().StringVarP(&configPath, "config", "c", "./gobetween.toml", "Path to configuration file")
RootCmd.AddCommand(FromFileCmd)
}

/**
* FromFile Command
*/
var FromFileCmd = &cobra.Command{
Use: "from-file",
Short: "Use config from file",
Run: func(cmd *cobra.Command, args []string) {

data, err := ioutil.ReadFile(configPath)
if err != nil {
log.Fatal(err)
}

var cfg config.Config
if err = codec.Decode(string(data), &cfg, format); err != nil {
log.Fatal(err)
}

start(&cfg)
},
}
33 changes: 33 additions & 0 deletions src/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* root.go - root cmd emulates from-file TODO: remove when time will come
*
* @author Yaroslav Pogrebnyak <[email protected]>
*/
package cmd

import (
"github.com/spf13/cobra"
)

/* Persistent parsed options */
var format string

/**
* Add Root Command
*/
func init() {
RootCmd.Flags().StringVarP(&configPath, "config", "c", "./gobetween.toml", "Path to configuration file")
RootCmd.PersistentFlags().StringVarP(&format, "format", "f", "toml", "Configuration file format: toml or json")
}

/**
* Root Command
*/
var RootCmd = &cobra.Command{
Use: "gobetween",
Short: "Modern & minimalistic load balancer for the Cload era",
Run: func(cmd *cobra.Command, args []string) {
// TODO: Remove when times will come to break backward-compatibility
FromFileCmd.Run(cmd, args)
},
}
1 change: 0 additions & 1 deletion src/info/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ import (
)

var Version string
var ConfigPath string
var StartTime time.Time
53 changes: 15 additions & 38 deletions src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,26 @@
* main.go - entry point
* @author Yaroslav Pogrebnyak <[email protected]>
*/

package main

import (
"./api"
"./cmd"
"./config"
"./info"
"./logging"
"./manager"
"flag"
"github.com/BurntSushi/toml"
"math/rand"
"os"
"runtime"
"time"
)

/**
* Constants
*/
const (
defaultConfigPath = "./gobetween.toml"
)

/**
* Version should be set while build
* using ldflags (see Makefile)
* Version should be set while build using ldflags (see Makefile)
*/
var version string

var configPath string

/**
* Initialize package
*/
Expand All @@ -47,41 +35,30 @@ func init() {
// Init random seed
rand.Seed(time.Now().UnixNano())

// Init command-line flags
flag.StringVar(&configPath, "c", defaultConfigPath, "Path to config file")

// Set info to be used in another parts of the program
// Save info
info.Version = version
info.ConfigPath = configPath
info.StartTime = time.Now()

}

/**
* Entry point
*/
func main() {

flag.Parse()

log := logging.For("main")
log.Info("gobetween v", version)
log.Info("Using config file ", configPath)

// Parse config
var cfg config.Config
if _, err := toml.DecodeFile(configPath, &cfg); err != nil {
log.Fatal(err)
}
// Process flags and start
cmd.Execute(func(cfg *config.Config) {

// Configure logging
logging.Configure(cfg.Logging.Output, cfg.Logging.Level)
// Configure logging
logging.Configure(cfg.Logging.Output, cfg.Logging.Level)

// Start API
go api.Start(cfg.Api)
// Start API
go api.Start((*cfg).Api)

// Start manager
go manager.Initialize(cfg)
// Start manager
go manager.Initialize(*cfg)

// block forever
<-(chan string)(nil)
// block forever
<-(chan string)(nil)
})
}
29 changes: 29 additions & 0 deletions src/utils/codec/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* codec.go - decoding utils
*
* @author Yaroslav Pogrebnyak <[email protected]>
*/
package codec

import (
"encoding/json"
"errors"
"github.com/BurntSushi/toml"
)

/**
* Decode data based on format
* Currently supported: toml and json
*/
func Decode(data string, out interface{}, format string) error {

switch format {
case "toml":
_, err := toml.Decode(data, out)
return err
case "json":
return json.Unmarshal([]byte(data), out)
default:
return errors.New("Unknown format " + format)
}
}

0 comments on commit f9c89f5

Please sign in to comment.