108 lines
1.9 KiB
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)
|
|
}
|