-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
344 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"FIRSTSTRING": "1.0.3", | ||
"SECONDINT": 300 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package sputnik | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/g41797/gonfig" | ||
) | ||
|
||
// ConfigFactory returns implementation of sputnik.ConfFactory based on github.com/tkanos/gonfig | ||
// - JSON format of config files | ||
// - Automatic matching of environment variables | ||
// - Env. variable for configuration "example" and key "kname" should be set in environment as "EXAMPLE_KNAME" | ||
// - Value in environment automatically overrides value from the file | ||
// - Temporary used github.com/g41797/gonfig (till merge of PR) | ||
func ConfigFactory(cfPath string) ConfFactory { | ||
cnf := newConfig(cfPath) | ||
return cnf.unmarshal | ||
} | ||
|
||
type config struct { | ||
confPath string | ||
} | ||
|
||
func newConfig(cfPath string) *config { | ||
return &config{confPath: cfPath} | ||
} | ||
|
||
func (conf *config) unmarshal(confName string, result any) error { | ||
fPath := filepath.Join(conf.confPath, strings.ToLower(confName)) | ||
fPath += ".json" | ||
_, err := os.Open(fPath) | ||
if err != nil { | ||
return err | ||
} | ||
err = gonfig.GetConf(fPath, result) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package sputnik_test | ||
|
||
import ( | ||
"os" | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/g41797/sputnik" | ||
) | ||
|
||
type TestConf struct { | ||
FIRSTSTRING string `mapstructure:"FIRSTSTRING"` | ||
SECONDINT int `mapstructure:"SECONDINT"` | ||
} | ||
|
||
func TestJSON(t *testing.T) { | ||
|
||
confFolderPath := "./_conf_test/" | ||
|
||
cfact := sputnik.ConfigFactory(confFolderPath) | ||
|
||
expected := defaults() | ||
|
||
var tf TestConf | ||
|
||
err := cfact("example", &tf) | ||
|
||
compare(t, err, tf, expected) | ||
} | ||
|
||
func TestENV(t *testing.T) { | ||
|
||
confFolderPath := "./_conf_test/" | ||
|
||
cfact := sputnik.ConfigFactory(confFolderPath) | ||
|
||
expected := defaults() | ||
expected.SECONDINT = 12345 | ||
|
||
os.Setenv("EXAMPLE_FIRSTSTRING", expected.FIRSTSTRING) | ||
|
||
os.Setenv("EXAMPLE_SECONDINT", strconv.Itoa((expected.SECONDINT))) | ||
|
||
secIntString, ok := os.LookupEnv("EXAMPLE_SECONDINT") | ||
|
||
if !ok { | ||
t.Errorf("Wrong working with environment") | ||
} | ||
|
||
if secIntString != "12345" { | ||
t.Errorf("Wrong test") | ||
} | ||
|
||
var tf TestConf | ||
|
||
err := cfact("example", &tf) | ||
|
||
compare(t, err, tf, expected) | ||
} | ||
|
||
func defaults() TestConf { | ||
return TestConf{"1.0.3", 300} | ||
} | ||
|
||
func compare(t *testing.T, getErr error, actual TestConf, expected TestConf) { | ||
|
||
if getErr != nil { | ||
t.Errorf("unmarshal error %v", getErr) | ||
} | ||
|
||
if actual.FIRSTSTRING != expected.FIRSTSTRING { | ||
t.Errorf("Expected %s Actual %s", expected.FIRSTSTRING, actual.FIRSTSTRING) | ||
} | ||
|
||
if actual.SECONDINT != expected.SECONDINT { | ||
t.Errorf("Expected %d Actual %d", expected.SECONDINT, actual.SECONDINT) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
github.com/g41797/gonfig v1.0.1 h1:ywgkhF3SbNJuFN9Hlm9n7Lp+KxqeupkNmFObn2ZpWs8= | ||
github.com/g41797/gonfig v1.0.1/go.mod h1:5iL4oHFpYi+c7AE4D1dZnlBleJzM71dX6HZBhEELF90= | ||
github.com/g41797/kissngoqueue v0.1.5 h1:UrnpxbjOnTnKj/EqpbLA9LjhYkHjnLWMZQqsz3AOBG8= | ||
github.com/g41797/kissngoqueue v0.1.5/go.mod h1:c1mGfrNWfEP2cHeX04Iji8qYGQevvUmZw5SPZM5M9Cs= | ||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= | ||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | ||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package sputnik | ||
|
||
import "log" | ||
|
||
const ( | ||
labelLen = 3 | ||
infoLabel = "[INF] " | ||
debugLabel = "[DBG] " | ||
warnLabel = "[WRN] " | ||
errorLabel = "[ERR] " | ||
fatalLabel = "[FTL] " | ||
traceLabel = "[TRC] " | ||
) | ||
|
||
type LoggerFactory func() *Logger | ||
|
||
type Logger struct { | ||
logger *log.Logger | ||
} | ||
|
||
func NewLogger(lg *log.Logger) *Logger { | ||
return &Logger{logger: lg} | ||
} | ||
|
||
// Noticef logs a notice statement | ||
func (l *Logger) Noticef(format string, v ...interface{}) { | ||
l.logger.Printf(infoLabel+format, v...) | ||
} | ||
|
||
// Warnf logs a warning statement | ||
func (l *Logger) Warnf(format string, v ...interface{}) { | ||
l.logger.Printf(warnLabel+format, v...) | ||
} | ||
|
||
// Errorf logs an error statement | ||
func (l *Logger) Errorf(format string, v ...interface{}) { | ||
l.logger.Printf(errorLabel+format, v...) | ||
} | ||
|
||
// Fatalf logs a fatal error | ||
func (l *Logger) Fatalf(format string, v ...interface{}) { | ||
l.logger.Fatalf(fatalLabel+format, v...) | ||
} | ||
|
||
// Debugf logs a debug statement | ||
func (l *Logger) Debugf(format string, v ...interface{}) { | ||
l.logger.Printf(debugLabel+format, v...) | ||
|
||
} | ||
|
||
// Tracef logs a trace statement | ||
func (l *Logger) Tracef(format string, v ...interface{}) { | ||
l.logger.Printf(traceLabel+format, v...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package sputnik | ||
|
||
import ( | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"time" | ||
) | ||
|
||
func Start(cntr ServerConnector) { | ||
|
||
var confFolder string | ||
flag.StringVar(&confFolder, "cf", "", "Path of folder with config files") | ||
flag.Parse() | ||
|
||
if len(confFolder) == 0 { | ||
fmt.Fprintln(os.Stderr, fmt.Errorf("-cf <path of config folder> - was not set!!!")) | ||
os.Exit(1) | ||
} | ||
|
||
rnr, err := StartRunner(confFolder, cntr) | ||
if err != nil { | ||
fmt.Fprintln(os.Stderr, err) | ||
os.Exit(1) | ||
} | ||
|
||
rnr.Wait() | ||
return | ||
|
||
} | ||
|
||
const brokerCheckTimeOut = time.Second | ||
|
||
type Runner struct { | ||
// ShootDown | ||
kill ShootDown | ||
// Signalling channel | ||
done chan struct{} | ||
} | ||
|
||
func StartRunner(confFolder string, cntr ServerConnector) (*Runner, error) { | ||
info, err := prepare(confFolder, cntr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
rnr := new(Runner) | ||
err = rnr.Start(info) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return rnr, nil | ||
} | ||
|
||
func (rnr *Runner) Stop() { | ||
if rnr == nil { | ||
return | ||
} | ||
if rnr.kill == nil { | ||
return | ||
} | ||
|
||
select { | ||
case <-rnr.done: | ||
return | ||
default: | ||
} | ||
|
||
rnr.kill() | ||
|
||
return | ||
} | ||
|
||
func (rnr *Runner) Wait() { | ||
if rnr == nil { | ||
return | ||
} | ||
|
||
<-rnr.done | ||
|
||
return | ||
} | ||
|
||
type runnerInfo struct { | ||
cfact ConfFactory | ||
cnt ServerConnector | ||
appBlocks []BlockDescriptor | ||
} | ||
|
||
func prepare(confFolder string, cntr ServerConnector) (*runnerInfo, error) { | ||
info, err := os.Stat(confFolder) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if !info.IsDir() { | ||
return nil, fmt.Errorf("%s is not the folder", confFolder) | ||
} | ||
|
||
ri := runnerInfo{} | ||
|
||
ri.cfact = ConfigFactory(confFolder) | ||
|
||
ri.cnt = cntr | ||
|
||
ri.appBlocks, err = ReadAppBlocks(confFolder) | ||
|
||
return &ri, err | ||
} | ||
|
||
func (rnr *Runner) Start(ri *runnerInfo) error { | ||
|
||
sp, err := NewSputnik( | ||
WithAppBlocks(ri.appBlocks), | ||
WithConfFactory(ri.cfact), | ||
WithConnector(ri.cnt, brokerCheckTimeOut), | ||
) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
launch, kill, err := sp.Prepare() | ||
|
||
if err != nil { | ||
return err | ||
} | ||
rnr.kill = kill | ||
rnr.done = make(chan struct{}) | ||
|
||
go func(l Launch, done chan struct{}) { | ||
l() | ||
close(done) | ||
}(launch, rnr.done) | ||
|
||
return nil | ||
} | ||
|
||
func ReadAppBlocks(confFolder string) ([]BlockDescriptor, error) { | ||
fPath := filepath.Join(confFolder, "blocks.json") | ||
|
||
blocksRaw, err := os.ReadFile(fPath) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var result []BlockDescriptor | ||
|
||
json.Unmarshal([]byte(blocksRaw), &result) | ||
|
||
return result, nil | ||
} |