nurse/config/app_config.go

108 lines
1.9 KiB
Go

package config
import (
"io"
"os"
"time"
)
type (
Option interface {
Extend(n Nurse) (Nurse, error)
}
OptionFunc func(n Nurse) (Nurse, error)
)
func (f OptionFunc) Extend(n Nurse) (Nurse, error) {
return f(n)
}
func New(opts ...Option) (*Nurse, error) {
var (
inst Nurse
err error
)
for i := range opts {
if inst, err = opts[i].Extend(inst); err != nil {
return nil, err
}
}
return &inst, nil
}
type Nurse struct {
Servers map[string]Server
Endpoints map[Route]EndpointSpec
CheckTimeout time.Duration
CheckAttempts uint
}
func (n Nurse) ServerLookup() (*ServerRegister, error) {
register := NewServerRegister()
for name, srv := range n.Servers {
if err := register.Register(name, srv); err != nil {
return nil, err
}
}
return register, nil
}
// Merge merges the current Nurse instance with another one
// giving the current instance precedence means no set value is overwritten
func (n Nurse) Merge(other Nurse) Nurse {
if n.CheckTimeout == 0 {
n.CheckTimeout = other.CheckTimeout
}
if n.CheckAttempts == 0 {
n.CheckAttempts = other.CheckAttempts
}
for name, srv := range other.Servers {
if _, ok := n.Servers[name]; !ok {
n.Servers[name] = srv
}
}
return n
}
func (n *Nurse) Unmarshal(reader io.ReadSeeker) error {
providers := []func(io.Reader) configDecoder{
newYAMLDecoder,
newJSONDecoder,
}
for i := range providers {
if err := n.tryUnmarshal(reader, providers[i]); err == nil {
return nil
}
}
return nil
}
func (n *Nurse) ReadFromFile(configFilePath string) error {
if file, err := os.Open(configFilePath); err != nil {
return err
} else {
defer func() {
_ = file.Close()
}()
return n.Unmarshal(file)
}
}
func (n *Nurse) tryUnmarshal(seeker io.ReadSeeker, prov func(reader io.Reader) configDecoder) error {
if _, err := seeker.Seek(0, 0); err != nil {
return err
}
decoder := prov(seeker)
return decoder.DecodeConfig(n)
}