Rework Monitoring, Prometheus, Status system

Package Monitoring :
- use packag dedicated to monitor component
- each monitor work as standalone server to monitor health
- collect metrics to export them to prometheus exporter

Package Prometheus :
- review to simplify use for API and not API metrics
- optimize code

Package Status :
- Rework to use Monitor package
- Rework to use native json / text Marshaller interface

Context :
- rework context config (context var) to use sync map and sync RWMutex (WORM)
- move gin context to dedicated sub package (dependancies of logger make circular dependencies)
- optimize code

Config :
- rework to optimize sync / collect of component
- rework status to monitor
- remove monitor managment from config to each component
- add a func to set default logger to implement inherit default logger options
- optimize code

IOUtils :
- isolate logger / closer interface as a usable & public interface & instance
- this interface / instance allow to collect io.closer over a context to close all if context is done

Logger :
- rework to use context.config map
- rework to use ioutils closer
- rework to allow options to inherit a default options, or the last version of options
- optimize code

Size :
- Add package Size to calculate and manipulate size Byte or bit
- Add encoding : Text/JSON/Yaml/Toml...
- Add option to défine default unit : Byte or bit

Other :
- adjust following code
- optimize code
- limit use of atomic value
- rework to use RWMutex instead of sync.Mutex to maximize capabilities of read instead of write
- remove 32bit build for CI/CD
- add darwin/arm64 build for CI/CD

Bump Dependencies
This commit is contained in:
nabbar
2023-02-21 16:24:43 +01:00
parent 771a66eff4
commit e3239db998
283 changed files with 20647 additions and 10554 deletions

View File

@@ -93,43 +93,21 @@ jobs:
continue-on-error: false
run: sudo apt-get install gcc-multilib gcc-mingw-w64
- name: Test Build Linux/amd64 with suffix
- name: Test Build Linux/amd64 with suffix/CGO
continue-on-error: false
run: |
CGO_ENABLED=0
GOOS=linux
GOARCH=amd64
GOAMD64=v4
IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"')" | tr '\n' '|')
go build -a -v -installsuffix cgo -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
- name: Test Build Linux/386 with suffix
continue-on-error: false
run: |
CGO_ENABLED=0
GOOS=linux
GOARCH=386
IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"')" | tr '\n' '|')
go build -a -v -installsuffix cgo -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 GOAMD64=v4 go build -a -v -race -installsuffix cgo -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
- name: Test Build Windows/amd64 with CGO
continue-on-error: false
run: |
CC=/usr/bin/x86_64-w64-mingw32-gcc
CGO_ENABLED=1
GOOS=windows
GOARCH=amd64
GOAMD64=v4
IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"')" | tr '\n' '|')
go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
CC=/usr/bin/x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 GOAMD64=v4 go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
- name: Test Build Windows/386 with CGO
- name: Test Build Darwin/arm64 with suffix/CGO
continue-on-error: false
run: |
CC=/usr/bin/i686-w64-mingw32-gcc
CGO_ENABLED=1
GOOS=windows
GOARCH=386
IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"')" | tr '\n' '|')
go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 GOAMD64=v1 go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})

View File

@@ -31,12 +31,12 @@ import (
"net"
"net/url"
libsts "github.com/nabbar/golib/status/config"
moncfg "github.com/nabbar/golib/monitor/types"
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
libval "github.com/go-playground/validator/v10"
"github.com/nabbar/golib/errors"
"github.com/nabbar/golib/httpcli"
liberr "github.com/nabbar/golib/errors"
libhtc "github.com/nabbar/golib/httpcli"
)
type Model struct {
@@ -47,8 +47,9 @@ type Model struct {
}
type ModelStatus struct {
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required,dive"`
Status libsts.ConfigStatus `json:"status" yaml:"status" toml:"status" mapstructure:"status" validate:"required,dive"`
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required,dive"`
HTTPClient libhtc.Options `json:"http-client" yaml:"http-client" toml:"http-client" mapstructure:"http-client" validate:"required,dive"`
Monitor moncfg.Config `json:"monitor" yaml:"monitor" toml:"monitor" mapstructure:"monitor" validate:"required,dive"`
}
type awsModel struct {
@@ -56,7 +57,7 @@ type awsModel struct {
retryer func() sdkaws.Retryer
}
func (c *awsModel) Validate() errors.Error {
func (c *awsModel) Validate() liberr.Error {
err := ErrorConfigValidator.Error(nil)
if er := libval.New().Struct(c); er != nil {
@@ -89,11 +90,11 @@ func (c *awsModel) SetCredentials(accessKey, secretKey string) {
func (c *awsModel) ResetRegionEndpoint() {
}
func (c *awsModel) RegisterRegionEndpoint(region string, endpoint *url.URL) errors.Error {
func (c *awsModel) RegisterRegionEndpoint(region string, endpoint *url.URL) liberr.Error {
return nil
}
func (c *awsModel) RegisterRegionAws(endpoint *url.URL) errors.Error {
func (c *awsModel) RegisterRegionAws(endpoint *url.URL) liberr.Error {
return nil
}
@@ -108,7 +109,7 @@ func (c *awsModel) GetRegion() string {
func (c *awsModel) SetEndpoint(endpoint *url.URL) {
}
func (c awsModel) GetEndpoint() *url.URL {
func (c *awsModel) GetEndpoint() *url.URL {
return nil
}
@@ -116,6 +117,18 @@ func (c *awsModel) ResolveEndpoint(service, region string) (sdkaws.Endpoint, err
return sdkaws.Endpoint{}, ErrorEndpointInvalid.Error(nil)
}
func (c *awsModel) ResolveEndpointWithOptions(service, region string, options ...interface{}) (sdkaws.Endpoint, error) {
return sdkaws.Endpoint{}, ErrorEndpointInvalid.Error(nil)
}
func (c *awsModel) GetDisableHTTPS() bool {
return false
}
func (c *awsModel) GetResolvedRegion() string {
return c.GetRegion()
}
func (c *awsModel) IsHTTPs() bool {
return true
}
@@ -124,14 +137,14 @@ func (c *awsModel) SetRetryer(retryer func() sdkaws.Retryer) {
c.retryer = retryer
}
func (c awsModel) Check(ctx context.Context) errors.Error {
func (c *awsModel) Check(ctx context.Context) liberr.Error {
var (
cfg *sdkaws.Config
con net.Conn
end sdkaws.Endpoint
adr *url.URL
err error
e errors.Error
e liberr.Error
)
if cfg, e = c.GetConfig(ctx, nil); e != nil {
@@ -142,7 +155,7 @@ func (c awsModel) Check(ctx context.Context) errors.Error {
ctx = context.Background()
}
if end, err = cfg.EndpointResolver.ResolveEndpoint("s3", c.GetRegion()); err != nil {
if end, err = cfg.EndpointResolverWithOptions.ResolveEndpoint("s3", c.GetRegion()); err != nil {
return ErrorEndpointInvalid.ErrorParent(err)
}
@@ -155,8 +168,8 @@ func (c awsModel) Check(ctx context.Context) errors.Error {
}
d := net.Dialer{
Timeout: httpcli.ClientTimeout5Sec,
KeepAlive: httpcli.ClientTimeout5Sec,
Timeout: libhtc.ClientTimeout5Sec,
KeepAlive: libhtc.ClientTimeout5Sec,
}
con, err = d.DialContext(ctx, "tcp", adr.Host)

View File

@@ -111,6 +111,7 @@ func (c *awsModel) GetConfig(ctx context.Context, cli *http.Client) (*sdkaws.Con
cfg.Credentials = sdkcrd.NewStaticCredentialsProvider(c.AccessKey, c.SecretKey, "")
cfg.Retryer = c.retryer
cfg.EndpointResolver = sdkaws.EndpointResolverFunc(c.ResolveEndpoint)
cfg.EndpointResolverWithOptions = sdkaws.EndpointResolverWithOptionsFunc(c.ResolveEndpointWithOptions)
cfg.Region = c.Region
if cli != nil {

View File

@@ -32,12 +32,13 @@ import (
"net/url"
"strings"
moncfg "github.com/nabbar/golib/monitor/types"
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
libval "github.com/go-playground/validator/v10"
liberr "github.com/nabbar/golib/errors"
libhtc "github.com/nabbar/golib/httpcli"
liblog "github.com/nabbar/golib/logger"
libsts "github.com/nabbar/golib/status/config"
)
type Model struct {
@@ -49,8 +50,9 @@ type Model struct {
}
type ModelStatus struct {
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required,dive"`
Status libsts.ConfigStatus `json:"status" yaml:"status" toml:"status" mapstructure:"status" validate:"required,dive"`
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required,dive"`
HTTPClient libhtc.Options `json:"http-client" yaml:"http-client" toml:"http-client" mapstructure:"http-client" validate:"required,dive"`
Monitor moncfg.Config `json:"monitor" yaml:"monitor" toml:"monitor" mapstructure:"monitor" validate:"required,dive"`
}
type awsModel struct {
@@ -220,11 +222,15 @@ func (c *awsModel) SetEndpoint(endpoint *url.URL) {
c.Endpoint = strings.TrimSuffix(c.endpoint.String(), "/")
}
func (c awsModel) GetEndpoint() *url.URL {
func (c *awsModel) GetEndpoint() *url.URL {
return c.endpoint
}
func (c *awsModel) ResolveEndpoint(service, region string) (sdkaws.Endpoint, error) {
return c.ResolveEndpointWithOptions(service, region)
}
func (c *awsModel) ResolveEndpointWithOptions(service, region string, options ...interface{}) (sdkaws.Endpoint, error) {
if e, ok := c.mapRegion[region]; ok {
return sdkaws.Endpoint{
URL: strings.TrimSuffix(e.String(), "/"),
@@ -245,6 +251,14 @@ func (c *awsModel) ResolveEndpoint(service, region string) (sdkaws.Endpoint, err
return sdkaws.Endpoint{}, ErrorEndpointInvalid.Error(nil)
}
func (c *awsModel) GetDisableHTTPS() bool {
return false
}
func (c *awsModel) GetResolvedRegion() string {
return c.GetRegion()
}
func (c *awsModel) IsHTTPs() bool {
return strings.HasSuffix(strings.ToLower(c.endpoint.Scheme), "s")
}
@@ -253,7 +267,7 @@ func (c *awsModel) SetRetryer(retryer func() sdkaws.Retryer) {
c.retryer = retryer
}
func (c awsModel) Check(ctx context.Context) liberr.Error {
func (c *awsModel) Check(ctx context.Context) liberr.Error {
var (
cfg *sdkaws.Config
con net.Conn
@@ -269,7 +283,7 @@ func (c awsModel) Check(ctx context.Context) liberr.Error {
ctx = context.Background()
}
if _, err = cfg.EndpointResolver.ResolveEndpoint("s3", c.GetRegion()); err != nil {
if _, err = cfg.EndpointResolverWithOptions.ResolveEndpoint("s3", c.GetRegion()); err != nil {
return ErrorEndpointInvalid.ErrorParent(err)
}

View File

@@ -61,6 +61,9 @@ type Config interface {
IsHTTPs() bool
ResolveEndpoint(service, region string) (sdkaws.Endpoint, error)
ResolveEndpointWithOptions(service, region string, options ...interface{}) (sdkaws.Endpoint, error)
GetDisableHTTPS() bool
GetResolvedRegion() string
SetRetryer(retryer func() sdkaws.Retryer)
GetConfig(ctx context.Context, cli *http.Client) (*sdkaws.Config, liberr.Error)

27
cache/expiration.go vendored Normal file
View File

@@ -0,0 +1,27 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package cache

73
cache/interface.go vendored Normal file
View File

@@ -0,0 +1,73 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package cache
import (
"context"
"sync"
"time"
)
type FuncCache[T any] func() Cache[T]
type Cache[T any] interface {
Clone(ctx context.Context, exp time.Duration) Cache[T]
Close()
Clean()
Merge(c Cache[T])
Walk(fct func(key any, val interface{}, exp time.Duration) bool)
Load(key any) (val interface{}, exp time.Duration, ok bool)
Store(key any, val interface{}) time.Duration
Delete(key any)
LoadOrStore(key any, val interface{}) (res interface{}, exp time.Duration, loaded bool)
LoadAndDelete(key any) (val interface{}, loaded bool)
}
func New[T any](ctx context.Context, exp time.Duration) Cache[T] {
if ctx == nil {
ctx = context.Background()
}
if exp < time.Microsecond {
return nil
}
n := &cache[T]{
Context: ctx,
w: sync.RWMutex{},
m: sync.Map{},
c: make(chan struct{}),
e: exp,
}
go n.ticker(exp)
return n
}

51
cache/item.go vendored Normal file
View File

@@ -0,0 +1,51 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package cache
import "time"
type cacheItem struct {
t time.Time
v interface{}
}
func store(val interface{}) *cacheItem {
return &cacheItem{
t: time.Now(),
v: val,
}
}
func parse(v any, exp time.Duration) (interface{}, time.Duration) {
if i, ok := v.(*cacheItem); !ok {
return nil, 0
} else if e := exp - time.Since(i.t); e < time.Microsecond {
return nil, 0
} else {
return i.v, e
}
}

218
cache/model.go vendored Normal file
View File

@@ -0,0 +1,218 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package cache
import (
"context"
"sync"
"time"
)
type cache[T any] struct {
context.Context
w sync.RWMutex
m sync.Map
c chan struct{}
e time.Duration
}
func (t *cache[T]) ticker(exp time.Duration) {
ticker := time.NewTicker(exp)
defer ticker.Stop()
for {
select {
case <-ticker.C:
t.expire()
case <-t.Done():
t.Clean()
return
case <-t.c:
t.Clean()
return
}
}
}
func (t *cache[T]) expire() {
t.w.RLock()
defer t.w.RUnlock()
exp := t.e
t.m.Range(func(key, value any) bool {
if v, _ := parse(value, exp); v == nil {
t.m.Delete(key)
}
return true
})
}
func (t *cache[T]) Clone(ctx context.Context, exp time.Duration) Cache[T] {
t.w.RLock()
defer t.w.RUnlock()
if ctx == nil {
ctx = t.Context
}
if exp < time.Microsecond {
exp = t.e
}
n := &cache[T]{
Context: ctx,
w: sync.RWMutex{},
m: sync.Map{},
c: make(chan struct{}),
e: exp,
}
t.m.Range(func(key any, val interface{}) bool {
n.Store(key, val)
return true
})
go n.ticker(exp)
return n
}
func (t *cache[T]) Close() {
t.c <- struct{}{}
}
func (t *cache[T]) Clean() {
t.w.Lock()
defer t.w.Unlock()
t.m = sync.Map{}
}
func (t *cache[T]) Merge(c Cache[T]) {
t.w.RLock()
defer t.w.RUnlock()
c.Walk(func(key any, val interface{}, exp time.Duration) bool {
t.m.Store(key, &cacheItem{
t: time.Now().Add(-exp),
v: nil,
})
return true
})
}
func (t *cache[T]) Walk(fct func(key any, val interface{}, exp time.Duration) bool) {
t.w.RLock()
defer t.w.RUnlock()
exp := t.e
t.m.Range(func(key, value any) bool {
if v, e := parse(value, exp); v == nil {
t.m.Delete(key)
return true
} else {
return fct(key, v, e)
}
})
}
func (t *cache[T]) Load(key any) (val interface{}, exp time.Duration, ok bool) {
t.w.RLock()
defer t.w.RUnlock()
var o any
if o, ok = t.m.Load(key); !ok {
return nil, 0, false
} else if val, exp = parse(o, t.e); val == nil {
t.m.Delete(key)
return nil, 0, false
} else {
return val, exp, true
}
}
func (t *cache[T]) Store(key any, val interface{}) time.Duration {
i := store(val)
e := time.Now()
t.w.RLock()
defer t.w.RUnlock()
t.m.Store(key, i)
return t.e - time.Since(e)
}
func (t *cache[T]) Delete(key any) {
t.m.LoadAndDelete(key)
}
func (t *cache[T]) LoadOrStore(key any, val interface{}) (res interface{}, exp time.Duration, loaded bool) {
if res, exp, loaded = t.Load(key); !loaded {
exp = t.Store(key, val)
return val, exp, false
}
return res, exp, loaded
}
func (t *cache[T]) LoadAndDelete(key any) (val interface{}, loaded bool) {
if val, _, loaded = t.Load(key); !loaded {
return nil, false
}
t.w.RLock()
defer t.w.RUnlock()
t.m.Delete(key)
return val, loaded
}
func (t *cache[T]) Deadline() (deadline time.Time, ok bool) {
return t.Context.Deadline()
}
func (t *cache[T]) Done() <-chan struct{} {
return t.Context.Done()
}
func (t *cache[T]) Err() error {
return t.Context.Err()
}
func (t *cache[T]) Value(key any) any {
if v, _, ok := t.Load(key); ok {
return v
} else {
return t.Context.Value(key)
}
}

View File

@@ -29,10 +29,14 @@ package certificates
import (
"crypto/tls"
"crypto/x509"
"net/http"
liberr "github.com/nabbar/golib/errors"
)
type FctHttpClient func(def TLSConfig, servername string) *http.Client
type FctTLSDefault func() TLSConfig
type TLSConfig interface {
AddRootCAString(rootCA string) bool
AddRootCAFile(pemFile string) liberr.Error

View File

@@ -36,11 +36,10 @@ import (
"strings"
"github.com/mitchellh/go-homedir"
"github.com/pelletier/go-toml"
"gopkg.in/yaml.v3"
liblog "github.com/nabbar/golib/logger"
"github.com/pelletier/go-toml"
spfcbr "github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)
var cfgFile string

361
config/components.go Normal file
View File

@@ -0,0 +1,361 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package config
import (
"bytes"
"encoding/json"
"fmt"
"io"
_const "github.com/nabbar/golib/config/const"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
spfcbr "github.com/spf13/cobra"
)
func (c *configModel) ComponentHas(key string) bool {
if i, l := c.cpt.Load(key); !l {
return false
} else {
_, k := i.(cfgtps.Component)
return k
}
}
func (c *configModel) ComponentType(key string) string {
if v := c.ComponentGet(key); v == nil {
return ""
} else {
return v.Type()
}
}
func (c *configModel) ComponentGet(key string) cfgtps.Component {
if i, l := c.cpt.Load(key); !l {
return nil
} else if v, k := i.(cfgtps.Component); !k {
return nil
} else {
return v
}
}
func (c *configModel) ComponentDel(key string) {
c.cpt.Delete(key)
}
func (c *configModel) ComponentSet(key string, cpt cfgtps.Component) {
cpt.Init(key, c.ctx.GetContext, c.ComponentGet, c.getViper, c.getVersion(), c.getDefaultLogger)
if f := c.getFctMonitorPool(); f != nil {
cpt.RegisterMonitorPool(f)
} else {
cpt.RegisterMonitorPool(c.getMonitorPool)
}
c.cpt.Store(key, cpt)
}
func (c *configModel) ComponentList() map[string]cfgtps.Component {
var res = make(map[string]cfgtps.Component, 0)
c.cpt.Walk(func(key string, val interface{}) bool {
if v, k := val.(cfgtps.Component); k {
res[key] = v
} else {
c.cpt.Delete(key)
}
return true
})
return res
}
func (c *configModel) ComponentKeys() []string {
var res = make([]string, 0)
c.cpt.Walk(func(key string, val interface{}) bool {
if _, k := val.(cfgtps.Component); k {
res = append(res, key)
} else {
c.cpt.Delete(key)
}
return true
})
return res
}
func (c *configModel) ComponentStart() liberr.Error {
var err = ErrorComponentStart.Error(nil)
c.cpt.Walk(func(key string, val interface{}) bool {
if v, k := val.(cfgtps.Component); !k {
c.cpt.Delete(key)
} else if v == nil {
c.cpt.Delete(key)
} else if e := c.startComponent(key, v); e != nil {
err.AddParent(e)
}
return true
})
if err.HasParent() {
return err
}
return nil
}
func (c *configModel) startComponent(key string, cpt cfgtps.Component) liberr.Error {
if cpt.IsStarted() {
return nil
} else if err := c.startDependencies(cpt.Dependencies()); err != nil {
return err
} else if err = cpt.Start(); err != nil {
return err
} else {
c.cpt.Store(key, cpt)
}
return nil
}
func (c *configModel) startDependencies(list []string) liberr.Error {
if len(list) < 1 {
return nil
}
for _, d := range list {
if cpt := c.ComponentGet(d); cpt == nil {
return ErrorComponentNotFound.ErrorParent(fmt.Errorf("cvomponent '%s' not found", d))
} else if cpt.IsStarted() {
continue
} else if err := c.startComponent(d, cpt); err != nil {
return err
}
}
return nil
}
func (c *configModel) ComponentIsStarted() bool {
isOk := false
c.cpt.Walk(func(key string, val interface{}) bool {
if v, k := val.(cfgtps.Component); !k {
c.cpt.Delete(key)
} else if v == nil {
c.cpt.Delete(key)
} else if v.IsStarted() {
isOk = true
return false
}
return true
})
return isOk
}
func (c *configModel) ComponentReload() liberr.Error {
var err = ErrorComponentReload.Error(nil)
c.cpt.Walk(func(key string, val interface{}) bool {
if v, k := val.(cfgtps.Component); !k {
c.cpt.Delete(key)
} else if v == nil {
c.cpt.Delete(key)
} else if e := c.reloadComponent(key, v); e != nil {
err.AddParent(e)
}
return true
})
if err.HasParent() {
return err
}
return nil
}
func (c *configModel) reloadComponent(key string, cpt cfgtps.Component) liberr.Error {
if cpt.IsStarted() {
return nil
} else if err := c.reloadDependencies(cpt.Dependencies()); err != nil {
return err
} else if err = cpt.Start(); err != nil {
return err
} else {
c.cpt.Store(key, cpt)
}
return nil
}
func (c *configModel) reloadDependencies(list []string) liberr.Error {
if len(list) < 1 {
return nil
}
for _, d := range list {
if cpt := c.ComponentGet(d); cpt == nil {
return ErrorComponentNotFound.ErrorParent(fmt.Errorf("cvomponent '%s' not found", d))
} else if cpt.IsStarted() {
continue
} else if err := c.startComponent(d, cpt); err != nil {
return err
}
}
return nil
}
func (c *configModel) ComponentStop() {
c.cpt.Walk(func(key string, val interface{}) bool {
if v, k := val.(cfgtps.Component); !k {
c.cpt.Delete(key)
} else if v == nil {
c.cpt.Delete(key)
} else if v.IsStarted() {
v.Stop()
}
return true
})
}
func (c *configModel) ComponentIsRunning(atLeast bool) bool {
isOk := false
c.cpt.Walk(func(key string, val interface{}) bool {
v, k := val.(cfgtps.Component)
if !k {
c.cpt.Delete(key)
return true
} else if v == nil {
c.cpt.Delete(key)
return true
}
if v.IsRunning() {
isOk = true
}
if atLeast && isOk {
return false
} else if !atLeast && !isOk {
return false
}
return true
})
return isOk
}
func (c *configModel) DefaultConfig() io.Reader {
var buffer = bytes.NewBuffer(make([]byte, 0))
buffer.WriteString("{")
buffer.WriteString("\n")
n := buffer.Len()
c.cpt.Walk(func(key string, val interface{}) bool {
v, k := val.(cfgtps.Component)
if !k {
c.ComponentDel(key)
return true
} else if v == nil {
c.ComponentDel(key)
return true
}
if p := v.DefaultConfig(_const.JSONIndent); len(p) > 0 {
if buffer.Len() > n {
buffer.WriteString(",")
buffer.WriteString("\n")
}
buffer.WriteString(fmt.Sprintf("%s\"%s\": ", _const.JSONIndent, key))
buffer.Write(p)
}
return true
})
buffer.WriteString("\n")
buffer.WriteString("}")
var (
cmp = bytes.NewBuffer(make([]byte, 0))
ind = bytes.NewBuffer(make([]byte, 0))
)
if err := json.Compact(cmp, buffer.Bytes()); err != nil {
return buffer
} else if err = json.Indent(ind, cmp.Bytes(), "", _const.JSONIndent); err != nil {
return buffer
}
return ind
}
func (c *configModel) RegisterFlag(Command *spfcbr.Command) error {
var err = ErrorComponentFlagError.Error(nil)
for _, k := range c.ComponentKeys() {
if cpt := c.ComponentGet(k); cpt == nil {
continue
} else if e := cpt.RegisterFlag(Command); e != nil {
err.AddParent(e)
} else {
c.ComponentSet(k, cpt)
}
}
if err.HasParent() {
return err
}
return nil
}
func (c *configModel) ComponentWalk(fct cfgtps.ComponentListWalkFunc) {
c.cpt.Walk(func(key string, val interface{}) bool {
if v, k := val.(cfgtps.Component); !k {
c.cpt.Delete(key)
return true
} else if v == nil {
c.cpt.Delete(key)
return true
} else {
return fct(key, v)
}
})
}

View File

@@ -0,0 +1,220 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package aws
import (
"net/http"
libaws "github.com/nabbar/golib/aws"
libtls "github.com/nabbar/golib/certificates"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentAws) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentAws) _getTLS() libtls.TLSConfig {
o.m.RLock()
defer o.m.RUnlock()
if o.t == nil {
return nil
}
return o.t()
}
func (o *componentAws) _getHttpClient() *http.Client {
o.m.RLock()
defer o.m.RUnlock()
if o.c == nil {
return &http.Client{}
}
return o.c()
}
func (o *componentAws) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentAws) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentAws) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentAws) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentAws) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentAws) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentAws) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentAws) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentAws) _runCli() liberr.Error {
var prt = ErrorComponentReload
if !o.IsStarted() {
prt = ErrorComponentStart
}
if cfg, mon, htc, err := o._getConfig(); err != nil {
return prt.Error(err)
} else if cli, er := libaws.New(o.x.GetContext(), cfg, o._getHttpClient()); er != nil {
return prt.Error(er)
} else {
o.m.Lock()
o.a = cli
o.m.Unlock()
if htc != nil {
o.RegisterHTTPClient(func() *http.Client {
if c, e := htc.GetClient(o._getTLS(), ""); e == nil {
return c
}
return &http.Client{}
})
}
if e := o._registerMonitor(mon, cfg); e != nil {
return prt.ErrorParent(e)
}
}
return nil
}
func (o *componentAws) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,155 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package aws
import (
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "aws"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentAws) Type() string {
return ComponentType
}
func (o *componentAws) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentAws) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentAws) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentAws) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o.a != nil
}
func (o *componentAws) IsRunning() bool {
return o.IsStarted()
}
func (o *componentAws) Start() liberr.Error {
return o._run()
}
func (o *componentAws) Reload() liberr.Error {
return o._run()
}
func (o *componentAws) Stop() {
o.m.Lock()
defer o.m.Unlock()
o.a = nil
return
}
func (o *componentAws) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = make([]string, 0)
if o == nil {
return def
} else if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentAws) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentAws) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,236 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package aws
import (
libaws "github.com/nabbar/golib/aws"
cfgstd "github.com/nabbar/golib/aws/configAws"
cfgcus "github.com/nabbar/golib/aws/configCustom"
liberr "github.com/nabbar/golib/errors"
libhtc "github.com/nabbar/golib/httpcli"
libmon "github.com/nabbar/golib/monitor/types"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
type _configFlag struct {
accessKey *string
secretKey *string
bucket *string
region *string
endpoint *string
}
func (c *_configFlag) updCustom(cfg *cfgcus.Model) {
if c.accessKey != nil {
cfg.AccessKey = *c.accessKey
}
if c.secretKey != nil {
cfg.SecretKey = *c.secretKey
}
if c.bucket != nil {
cfg.Bucket = *c.bucket
}
if c.region != nil {
cfg.Region = *c.region
}
if c.endpoint != nil {
cfg.Endpoint = *c.endpoint
}
}
func (c *_configFlag) updStandard(cfg *cfgstd.Model) {
if c.accessKey != nil {
cfg.AccessKey = *c.accessKey
}
if c.secretKey != nil {
cfg.SecretKey = *c.secretKey
}
if c.bucket != nil {
cfg.Bucket = *c.bucket
}
if c.region != nil {
cfg.Region = *c.region
}
}
func (o *componentAws) RegisterFlag(Command *spfcbr.Command) error {
var (
key = o._getKey()
vpr *spfvpr.Viper
)
if vpr = o._getSPFViper(); vpr == nil {
return ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
}
_ = Command.PersistentFlags().String(key+".access-key", "", "AWS Access Key")
_ = Command.PersistentFlags().String(key+".secret-key", "", "AWS Secret Key")
_ = Command.PersistentFlags().String(key+".bucket", "", "Bucket to use")
_ = Command.PersistentFlags().String(key+".region", "", "Region for bucket")
_ = Command.PersistentFlags().String(key+".endpoint", "", "Endpoint if necessary for the region")
if err := vpr.BindPFlag(key+".access-key", Command.PersistentFlags().Lookup(key+".access-key")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".secret-key", Command.PersistentFlags().Lookup(key+".secret-key")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".bucket", Command.PersistentFlags().Lookup(key+".bucket")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".region", Command.PersistentFlags().Lookup(key+".region")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".endpoint", Command.PersistentFlags().Lookup(key+".endpoint")); err != nil {
return err
}
return nil
}
func (o *componentAws) _getConfig() (libaws.Config, *libmon.Config, *libhtc.Options, liberr.Error) {
var (
key string
cfg libaws.Config
flg = o._getFlagUpdate()
mon *libmon.Config
htc *libhtc.Options
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, nil, nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, nil, nil, ErrorComponentNotInitialized.Error(nil)
}
switch o.d {
case ConfigCustomStatus:
cnf := cfgcus.ModelStatus{}
if e := vpr.UnmarshalKey(key, &cnf); e != nil {
return nil, nil, nil, ErrorParamInvalid.ErrorParent(e)
} else {
flg.updCustom(&cnf.Config)
}
if cfg, err = o.d.NewFromModel(cnf); err != nil {
return nil, nil, nil, err
} else {
mon = &cnf.Monitor
htc = &cnf.HTTPClient
}
case ConfigCustom:
cnf := cfgcus.Model{}
if e := vpr.UnmarshalKey(key, &cnf); e != nil {
return nil, nil, nil, ErrorParamInvalid.ErrorParent(e)
} else {
flg.updCustom(&cnf)
}
if cfg, err = o.d.NewFromModel(cnf); err != nil {
return nil, nil, nil, err
} else {
mon = nil
htc = nil
}
case ConfigStandardStatus:
cnf := cfgstd.ModelStatus{}
if e := vpr.UnmarshalKey(key, &cnf); e != nil {
return nil, nil, nil, ErrorParamInvalid.ErrorParent(e)
} else {
flg.updStandard(&cnf.Config)
}
if cfg, err = o.d.NewFromModel(cnf); err != nil {
return nil, nil, nil, err
} else {
mon = &cnf.Monitor
htc = &cnf.HTTPClient
}
case ConfigStandard:
cnf := cfgstd.Model{}
if e := vpr.UnmarshalKey(key, &cnf); e != nil {
return nil, nil, nil, ErrorParamInvalid.ErrorParent(e)
} else {
flg.updStandard(&cnf)
}
if cfg, err = o.d.NewFromModel(cnf); err != nil {
return nil, nil, nil, err
} else {
mon = nil
htc = nil
}
}
if err = cfg.Validate(); err != nil {
return nil, nil, nil, ErrorConfigInvalid.Error(err)
}
return cfg, mon, htc, nil
}
func (o *componentAws) _getFlagUpdate() *_configFlag {
var (
cfg = &_configFlag{
accessKey: nil,
secretKey: nil,
bucket: nil,
region: nil,
endpoint: nil,
}
vpr *spfvpr.Viper
key string
)
if vpr = o._getSPFViper(); vpr == nil {
return nil
} else if key = o._getKey(); len(key) < 1 {
return nil
}
if s := vpr.GetString(key + ".access-key"); s != "" {
cfg.accessKey = &s
}
if s := vpr.GetString(key + ".secret-key"); s != "" {
cfg.secretKey = &s
}
if s := vpr.GetString(key + ".bucket"); s != "" {
cfg.bucket = &s
}
if s := vpr.GetString(key + ".region"); s != "" {
cfg.region = &s
}
if s := vpr.GetString(key + ".endpoint"); s != "" {
cfg.endpoint = &s
}
return cfg
}

View File

@@ -30,14 +30,9 @@ import (
"bytes"
"encoding/json"
libaws "github.com/nabbar/golib/aws"
cfgstd "github.com/nabbar/golib/aws/configAws"
cfgcus "github.com/nabbar/golib/aws/configCustom"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
libsts "github.com/nabbar/golib/status/config"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgcst "github.com/nabbar/golib/config/const"
libhtc "github.com/nabbar/golib/httpcli"
montps "github.com/nabbar/golib/monitor/types"
)
var _defaultConfigStandard = []byte(`{
@@ -49,12 +44,9 @@ var _defaultConfigStandard = []byte(`{
}`)
var _defaultConfigStandardWithStatus = []byte(`{
"bucket": "",
"accesskey": "",
"secretkey": "",
"region": "",
"endpoint": "",
"status":` + string(libsts.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
"config":` + string(DefaultConfigStandard(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"http-client":` + string(libhtc.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"monitor":` + string(montps.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `
}`)
var _defaultConfigCustom = []byte(`{
@@ -66,12 +58,9 @@ var _defaultConfigCustom = []byte(`{
}`)
var _defaultConfigCustomWithStatus = []byte(`{
"bucket": "",
"accesskey": "",
"secretkey": "",
"region": "",
"endpoint": "",
"status":` + string(libsts.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
"config":` + string(DefaultConfigCustom(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"http-client":` + string(libhtc.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"monitor":` + string(montps.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `
}`)
var _defaultConfig = _defaultConfigCustom
@@ -96,145 +85,51 @@ func SetDefaultConfigCustom(withStatus bool) {
}
}
func DefaultConfig(indent string) []byte {
func DefaultConfigStandard(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfigStandard, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentAws) DefaultConfig(indent string) []byte {
func DefaultConfigStandardStatus(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfigStandardWithStatus, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func DefaultConfigCustom(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfigCustom, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func DefaultConfigCustomStatus(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfigCustomWithStatus, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (o *componentAws) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentAws) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
_ = Command.PersistentFlags().String(c.key+".access-key", "", "AWS Access Key")
_ = Command.PersistentFlags().String(c.key+".secret-key", "", "AWS Secret Key")
_ = Command.PersistentFlags().String(c.key+".bucket", "", "Bucket to use")
_ = Command.PersistentFlags().String(c.key+".region", "", "Region for bucket")
_ = Command.PersistentFlags().String(c.key+".endpoint", "", "Endpoint if necessary for the region")
if err := Viper.BindPFlag(c.key+".access-key", Command.PersistentFlags().Lookup(c.key+".access-key")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".secret-key", Command.PersistentFlags().Lookup(c.key+".secret-key")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".bucket", Command.PersistentFlags().Lookup(c.key+".bucket")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".region", Command.PersistentFlags().Lookup(c.key+".region")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".endpoint", Command.PersistentFlags().Lookup(c.key+".endpoint")); err != nil {
return err
}
return nil
}
func (c *componentAws) _getConfig(getCfg libcfg.FuncComponentConfigGet) (libaws.Config, *libsts.ConfigStatus, liberr.Error) {
var (
vpr = c.vpr()
cfg libaws.Config
sts *libsts.ConfigStatus
err liberr.Error
)
switch c.d {
case ConfigCustomStatus:
cnf := cfgcus.ModelStatus{}
if e := getCfg(c.key, &cnf); e != nil {
return nil, nil, ErrorParamInvalid.Error(e)
}
if s := vpr.GetString(c.key + ".access-key"); s != "" {
cnf.Config.AccessKey = s
}
if s := vpr.GetString(c.key + ".secret-key"); s != "" {
cnf.Config.SecretKey = s
}
if s := vpr.GetString(c.key + ".bucket"); s != "" {
cnf.Config.Bucket = s
}
if s := vpr.GetString(c.key + ".region"); s != "" {
cnf.Config.Region = s
}
if s := vpr.GetString(c.key + ".endpoint"); s != "" {
cnf.Config.Endpoint = s
}
if cfg, err = c.d.NewFromModel(cnf); err != nil {
return nil, nil, err
} else {
sts = &cnf.Status
}
case ConfigCustom:
cnf := cfgcus.Model{}
if e := getCfg(c.key, &cnf); e != nil {
return nil, nil, ErrorParamInvalid.Error(e)
}
if s := vpr.GetString(c.key + ".access-key"); s != "" {
cnf.AccessKey = s
}
if s := vpr.GetString(c.key + ".secret-key"); s != "" {
cnf.SecretKey = s
}
if s := vpr.GetString(c.key + ".bucket"); s != "" {
cnf.Bucket = s
}
if s := vpr.GetString(c.key + ".region"); s != "" {
cnf.Region = s
}
if s := vpr.GetString(c.key + ".endpoint"); s != "" {
cnf.Endpoint = s
}
if cfg, err = c.d.NewFromModel(cnf); err != nil {
return nil, nil, err
}
case ConfigStandardStatus:
cnf := cfgstd.ModelStatus{}
if e := getCfg(c.key, &cnf); e != nil {
return nil, nil, ErrorParamInvalid.Error(e)
}
if s := vpr.GetString(c.key + ".access-key"); s != "" {
cnf.Config.AccessKey = s
}
if s := vpr.GetString(c.key + ".secret-key"); s != "" {
cnf.Config.SecretKey = s
}
if s := vpr.GetString(c.key + ".bucket"); s != "" {
cnf.Config.Bucket = s
}
if s := vpr.GetString(c.key + ".region"); s != "" {
cnf.Config.Region = s
}
if cfg, err = c.d.NewFromModel(cnf); err != nil {
return nil, nil, err
} else {
sts = &cnf.Status
}
case ConfigStandard:
cnf := cfgstd.Model{}
if e := getCfg(c.key, &cnf); e != nil {
return nil, nil, ErrorParamInvalid.Error(e)
}
if s := vpr.GetString(c.key + ".access-key"); s != "" {
cnf.AccessKey = s
}
if s := vpr.GetString(c.key + ".secret-key"); s != "" {
cnf.SecretKey = s
}
if s := vpr.GetString(c.key + ".bucket"); s != "" {
cnf.Bucket = s
}
if s := vpr.GetString(c.key + ".region"); s != "" {
cnf.Region = s
}
if cfg, err = c.d.NewFromModel(cnf); err != nil {
return nil, nil, err
}
}
if err = cfg.Validate(); err != nil {
return nil, nil, ErrorConfigInvalid.Error(err)
}
return cfg, sts, nil
}

View File

@@ -38,8 +38,8 @@ const (
ErrorParamInvalid
ErrorComponentNotInitialized
ErrorConfigInvalid
ErrorStartComponent
ErrorReloadComponent
ErrorComponentStart
ErrorComponentReload
ErrorDependencyLogDefault
)
@@ -60,9 +60,9 @@ func getMessage(code liberr.CodeError) (message string) {
return "this component seems to not be correctly initialized"
case ErrorConfigInvalid:
return "invalid component config"
case ErrorStartComponent:
case ErrorComponentStart:
return "cannot start component with config"
case ErrorReloadComponent:
case ErrorComponentReload:
return "cannot reload component with new config"
case ErrorDependencyLogDefault:
return "cannot retrieve default Logger"

View File

@@ -31,32 +31,36 @@ import (
"sync"
libaws "github.com/nabbar/golib/aws"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
)
const (
ComponentType = "aws"
)
type ComponentAwsClient interface {
cfgtps.Component
RegisterHTTPClient(fct func() *http.Client)
}
type ComponentAwsAPI interface {
cfgtps.Component
RegisterTLS(fct libtls.FctTLSDefault)
}
type ComponentAws interface {
libcfg.Component
RegisterHTTPClient(fct func() *http.Client)
ComponentAwsClient
ComponentAwsAPI
GetAws() (libaws.AWS, liberr.Error)
SetAws(a libaws.AWS)
}
func New(drv ConfigDriver) ComponentAws {
return &componentAws{
ctx: nil,
get: nil,
fsa: nil,
fsb: nil,
fra: nil,
frb: nil,
m: sync.Mutex{},
d: drv,
a: nil,
m: sync.RWMutex{},
x: nil,
d: drv,
a: nil,
}
}
@@ -68,7 +72,7 @@ func RegisterNew(cfg libcfg.Config, drv ConfigDriver, key string) {
cfg.ComponentSet(key, New(drv))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentAws {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentAws {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentAws); !ok {

View File

@@ -31,177 +31,50 @@ import (
"sync"
libaws "github.com/nabbar/golib/aws"
libcfg "github.com/nabbar/golib/config"
libtls "github.com/nabbar/golib/certificates"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
libsts "github.com/nabbar/golib/status"
stscfg "github.com/nabbar/golib/status/config"
montps "github.com/nabbar/golib/monitor/types"
)
type componentAws struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
sts libcfg.FuncRouteStatus
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
fsi libsts.FctInfo
fsh libsts.FctHealth
m sync.Mutex
m sync.RWMutex
x libctx.Config[uint8]
d ConfigDriver
p montps.FuncPool
c func() *http.Client
t libtls.FctTLSDefault
a libaws.AWS
s stscfg.ConfigStatus
}
func (c *componentAws) _getHttpClient() *http.Client {
if c.c == nil {
return &http.Client{}
}
func (o *componentAws) RegisterHTTPClient(fct func() *http.Client) {
o.m.Lock()
defer o.m.Unlock()
return c.c()
o.c = fct
}
func (c *componentAws) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
func (o *componentAws) RegisterTLS(fct libtls.FctTLSDefault) {
o.m.Lock()
defer o.m.Unlock()
if c.a != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
o.t = fct
}
func (c *componentAws) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
func (o *componentAws) GetAws() (libaws.AWS, liberr.Error) {
o.m.RLock()
defer o.m.RUnlock()
return nil
}
func (c *componentAws) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
if cfg, sts, err := c._getConfig(getCfg); err != nil {
return err
} else if cli, er := libaws.New(c.ctx(), cfg, c._getHttpClient()); er != nil {
return er
} else {
c.a = cli
if sts != nil && c.sts != nil && c.fsi != nil && c.fsh != nil {
sts.RegisterStatus(c.sts(), c.key, c.fsi, c.fsh)
}
}
return nil
}
func (c *componentAws) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentAws) Type() string {
return ComponentType
}
func (c *componentAws) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentAws) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentAws) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentAws) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c.a != nil
}
func (c *componentAws) IsRunning(atLeast bool) bool {
return c.IsStarted()
}
func (c *componentAws) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentAws) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentAws) Stop() {
c.m.Lock()
defer c.m.Unlock()
c.a = nil
return
}
func (c *componentAws) Dependencies() []string {
return make([]string, 0)
}
func (c *componentAws) RegisterHTTPClient(fct func() *http.Client) {
c.m.Lock()
defer c.m.Unlock()
c.c = fct
}
func (c *componentAws) GetAws() (libaws.AWS, liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
if c.a == nil {
if o.a == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else {
return c.a.Clone(c.ctx())
return o.a.Clone(o.x.GetContext())
}
}
func (c *componentAws) SetAws(a libaws.AWS) {
c.m.Lock()
defer c.m.Unlock()
func (o *componentAws) SetAws(a libaws.AWS) {
o.m.Lock()
defer o.m.Unlock()
c.a = a
o.a = a
}

View File

@@ -0,0 +1,178 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package aws
import (
"context"
"fmt"
"runtime"
libaws "github.com/nabbar/golib/aws"
libmon "github.com/nabbar/golib/monitor"
moninf "github.com/nabbar/golib/monitor/info"
montps "github.com/nabbar/golib/monitor/types"
)
const (
defaultNameMonitor = "AWS Client"
)
func (o *componentAws) RegisterMonitorPool(fct montps.FuncPool) {
o.m.Lock()
defer o.m.Unlock()
o.p = fct
}
func (o *componentAws) _getMonitorPool() montps.Pool {
o.m.RLock()
defer o.m.RUnlock()
if o.p == nil {
return nil
} else if p := o.p(); p == nil {
return nil
} else {
return p
}
}
func (o *componentAws) _registerMonitor(cfg *montps.Config, aws libaws.Config) error {
var (
e error
key = o._getKey()
inf moninf.Info
mon montps.Monitor
res = make(map[string]interface{}, 0)
vrs = o._getVersion()
)
if o._getMonitorPool() == nil {
return nil
} else if len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
} else if cfg == nil {
return nil
} else if aws == nil {
return ErrorConfigInvalid.Error(nil)
}
res["runtime"] = runtime.Version()[2:]
if vrs != nil {
res["release"] = vrs.GetRelease()
res["build"] = vrs.GetBuild()
res["date"] = vrs.GetDate()
res["endpoint"] = aws.GetEndpoint().Host
res["region"] = aws.GetRegion()
}
if inf, e = moninf.New(defaultNameMonitor); e != nil {
return e
} else if vrs != nil {
inf.RegisterName(func() (string, error) {
return fmt.Sprintf("%s %s", defaultNameMonitor, o._getKey()), nil
})
inf.RegisterInfo(func() (map[string]interface{}, error) {
return res, nil
})
}
if mon = o._getMonitor(key, inf); mon == nil {
if mon, e = o._newMonitor(inf); e != nil {
return e
} else if mon == nil {
return nil
}
}
if e = mon.SetConfig(o.x.GetContext, *cfg); e != nil {
return e
}
mon.SetHealthCheck(o.HealthCheck)
if e = mon.Restart(o.x.GetContext()); e != nil {
return e
} else if e = o._setMonitor(mon); e != nil {
return e
}
return nil
}
func (o *componentAws) _newMonitor(inf montps.Info) (montps.Monitor, error) {
if c, e := libmon.New(o.x.GetContext, inf); e != nil {
return nil, e
} else if c != nil {
c.RegisterLoggerDefault(o.getLogger)
return c, nil
} else {
return c, nil
}
}
func (o *componentAws) _getMonitor(key string, inf montps.Info) montps.Monitor {
var (
mon libmon.Monitor
pol = o._getMonitorPool()
)
if pol == nil {
return nil
}
mon = pol.MonitorGet(key)
if mon != nil {
mon.InfoUpd(inf)
mon.RegisterLoggerDefault(o.getLogger)
}
return mon
}
func (o *componentAws) _setMonitor(mon montps.Monitor) error {
var pol = o._getMonitorPool()
if pol == nil {
return nil
}
return pol.MonitorSet(mon)
}
func (o *componentAws) HealthCheck(ctx context.Context) error {
o.m.RLock()
defer o.m.RUnlock()
if !o.IsStarted() {
return fmt.Errorf("component not started")
} else {
return o.a.Config().Check(ctx)
}
}

View File

@@ -0,0 +1,203 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package database
import (
"context"
cfgtps "github.com/nabbar/golib/config/types"
libdbs "github.com/nabbar/golib/database"
liberr "github.com/nabbar/golib/errors"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentDatabase) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentDatabase) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentDatabase) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentDatabase) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentDatabase) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentDatabase) _getContext() context.Context {
o.m.RLock()
defer o.m.RUnlock()
return o.x.GetContext()
}
func (o *componentDatabase) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentDatabase) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentDatabase) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentDatabase) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentDatabase) _runCli() liberr.Error {
var (
err liberr.Error
prt = ErrorComponentReload
dbo libdbs.Database
cfg *libdbs.Config
)
if !o.IsStarted() {
prt = ErrorComponentStart
}
if cfg, err = o._getConfig(); err != nil {
return prt.Error(err)
}
if dbo, err = libdbs.New(cfg); err != nil {
return prt.Error(err)
}
o.Stop()
o.m.Lock()
o.d = dbo
o.m.Unlock()
if e := o._registerMonitor(cfg); e != nil {
return prt.ErrorParent(e)
}
return nil
}
func (o *componentDatabase) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,168 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package database
import (
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "database"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentDatabase) Type() string {
return ComponentType
}
func (o *componentDatabase) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentDatabase) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentDatabase) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentDatabase) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o != nil && o.d != nil
}
func (o *componentDatabase) IsRunning() bool {
if !o.IsStarted() {
return false
} else if db := o.GetDatabase(); db == nil {
return false
} else if e := db.CheckConn(); e != nil {
return false
}
return true
}
func (o *componentDatabase) Start() liberr.Error {
return o._run()
}
func (o *componentDatabase) Reload() liberr.Error {
return o._run()
}
func (o *componentDatabase) Stop() {
o.m.Lock()
defer o.m.Unlock()
if o.d != nil {
o.d.Close()
}
o.d = nil
return
}
func (o *componentDatabase) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = make([]string, 0)
if o == nil {
return def
} else if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentDatabase) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentDatabase) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,191 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package database
import (
"time"
libdbs "github.com/nabbar/golib/database"
liberr "github.com/nabbar/golib/errors"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentDatabase) RegisterFlag(Command *spfcbr.Command) error {
var (
key string
vpr *spfvpr.Viper
)
if vpr = o._getSPFViper(); vpr == nil {
return ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
}
_ = Command.PersistentFlags().String(key+".driver", "", "driver to use for the DSN. It must be one of mysql, psql, sqlite, sqlserver, clickhouse.")
_ = Command.PersistentFlags().String(key+".name", "", "string to identify the instance into status.")
_ = Command.PersistentFlags().String(key+".dsn", "", "string options to connect to database following database engine. See https://gorm.io/docs/connecting_to_the_database.html for more information.")
_ = Command.PersistentFlags().Bool(key+".skip-default-transaction", false, "disable the default transaction for single create, update, delete operations.")
_ = Command.PersistentFlags().Bool(key+".full-save-associations", false, "full save associations")
_ = Command.PersistentFlags().Bool(key+".dry-run", false, "generate sql without execute")
_ = Command.PersistentFlags().Bool(key+".prepare-stmt", false, "executes the given query in cached statement")
_ = Command.PersistentFlags().Bool(key+".disable-automatic-ping", false, "is used to disable the automatic ping to the database server")
_ = Command.PersistentFlags().Bool(key+".disable-foreign-key-constraint-when-migrating", false, "is used to disable the foreign key constraint when migrating the database")
_ = Command.PersistentFlags().Bool(key+".disable-nested-transaction", false, "disable nested transaction")
_ = Command.PersistentFlags().Bool(key+".allow-global-update", false, "allow global update")
_ = Command.PersistentFlags().Bool(key+".query-fields", false, "executes the SQL query with all fields of the table")
_ = Command.PersistentFlags().Int(key+".create-batch-size", 0, "default create batch size")
_ = Command.PersistentFlags().Bool(key+".enable-connection-pool", false, "is used to create a connection pool")
_ = Command.PersistentFlags().Int(key+".pool-max-idle-conns", 0, "sets the maximum number of connections idle in the connection pool if enable")
_ = Command.PersistentFlags().Int(key+".pool-max-open-conns", 0, "sets the maximum number of connections open in the connection pool if enable")
_ = Command.PersistentFlags().Duration(key+".pool-conn-max-lifetime", 5*time.Minute, "sets the maximum lifetime of connections in the connection pool if enable")
_ = Command.PersistentFlags().Bool(key+".disabled", false, "allow to disable a database connection without clean his configuration")
if err := vpr.BindPFlag(key+".driver", Command.PersistentFlags().Lookup(key+".driver")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".name", Command.PersistentFlags().Lookup(key+".name")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".dsn", Command.PersistentFlags().Lookup(key+".dsn")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".skip-default-transaction", Command.PersistentFlags().Lookup(key+".skip-default-transaction")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".full-save-associations", Command.PersistentFlags().Lookup(key+".full-save-associations")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".dry-run", Command.PersistentFlags().Lookup(key+".dry-run")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".prepare-stmt", Command.PersistentFlags().Lookup(key+".prepare-stmt")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".disable-automatic-ping", Command.PersistentFlags().Lookup(key+".disable-automatic-ping")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".disable-foreign-key-constraint-when-migrating", Command.PersistentFlags().Lookup(key+".disable-foreign-key-constraint-when-migrating")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".disable-nested-transaction", Command.PersistentFlags().Lookup(key+".disable-nested-transaction")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".allow-global-update", Command.PersistentFlags().Lookup(key+".allow-global-update")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".query-fields", Command.PersistentFlags().Lookup(key+".query-fields")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".create-batch-size", Command.PersistentFlags().Lookup(key+".create-batch-size")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".enable-connection-pool", Command.PersistentFlags().Lookup(key+".enable-connection-pool")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".pool-max-idle-conns", Command.PersistentFlags().Lookup(key+".pool-max-idle-conns")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".pool-max-open-conns", Command.PersistentFlags().Lookup(key+".pool-max-open-conns")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".pool-conn-max-lifetime", Command.PersistentFlags().Lookup(key+".pool-conn-max-lifetime")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".disabled", Command.PersistentFlags().Lookup(key+".disabled")); err != nil {
return err
}
return nil
}
func (o *componentDatabase) _getConfig() (*libdbs.Config, liberr.Error) {
var (
key string
cfg libdbs.Config
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
cfg.RegisterLogger(o.getLogger, o.li, o.ls)
cfg.RegisterContext(o.x.GetContext)
if val := vpr.GetString(key + ".driver"); val != "" {
cfg.Driver = libdbs.DriverFromString(val)
}
if val := vpr.GetString(key + ".name"); val != "" {
cfg.Name = val
}
if val := vpr.GetString(key + ".dsn"); val != "" {
cfg.DSN = val
}
if val := vpr.GetBool(key + ".skip-default-transaction"); val {
cfg.SkipDefaultTransaction = true
}
if val := vpr.GetBool(key + ".full-save-associations"); val {
cfg.FullSaveAssociations = true
}
if val := vpr.GetBool(key + ".dry-run"); val {
cfg.DryRun = true
}
if val := vpr.GetBool(key + ".prepare-stmt"); val {
cfg.PrepareStmt = true
}
if val := vpr.GetBool(key + ".disable-automatic-ping"); val {
cfg.DisableAutomaticPing = true
}
if val := vpr.GetBool(key + ".disable-foreign-key-constraint-when-migrating"); val {
cfg.DisableForeignKeyConstraintWhenMigrating = true
}
if val := vpr.GetBool(key + ".disable-nested-transaction"); val {
cfg.DisableNestedTransaction = true
}
if val := vpr.GetBool(key + ".allow-global-update"); val {
cfg.AllowGlobalUpdate = true
}
if val := vpr.GetBool(key + ".query-fields"); val {
cfg.QueryFields = true
}
if val := vpr.GetInt(key + ".create-batch-size"); val != 0 {
cfg.CreateBatchSize = val
}
if val := vpr.GetBool(key + ".enable-connection-pool"); val {
cfg.EnableConnectionPool = true
}
if val := vpr.GetInt(key + ".pool-max-idle-conns"); val != 0 {
cfg.PoolMaxIdleConns = val
}
if val := vpr.GetInt(key + ".pool-max-open-conns"); val != 0 {
cfg.PoolMaxOpenConns = val
}
if val := vpr.GetDuration(key + ".pool-conn-max-lifetime"); val != 0 {
cfg.PoolConnMaxLifetime = val
}
if val := vpr.GetBool(key + ".disabled"); val {
cfg.Disabled = true
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -29,15 +29,9 @@ package database
import (
"bytes"
"encoding/json"
"time"
libcfg "github.com/nabbar/golib/config"
libdbs "github.com/nabbar/golib/database"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libsts "github.com/nabbar/golib/status/config"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgcst "github.com/nabbar/golib/config/const"
moncfg "github.com/nabbar/golib/monitor/types"
)
var _defaultConfig = []byte(`{
@@ -59,7 +53,7 @@ var _defaultConfig = []byte(`{
"pool-max-open-conns": 0,
"pool-conn-max-lifetime": "0s",
"disabled": false,
"status": ` + string(libsts.DefaultConfig(libcfg.JSONIndent)) + `
"monitor": ` + string(moncfg.DefaultConfig(cfgcst.JSONIndent)) + `
}`)
func SetDefaultConfig(cfg []byte) {
@@ -68,163 +62,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentDatabase) DefaultConfig(indent string) []byte {
func (o *componentDatabase) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentDatabase) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
_ = Command.PersistentFlags().String(c.key+".driver", "", "driver to use for the DSN. It must be one of mysql, psql, sqlite, sqlserver, clickhouse.")
_ = Command.PersistentFlags().String(c.key+".name", "", "string to identify the instance into status.")
_ = Command.PersistentFlags().String(c.key+".dsn", "", "string options to connect to database following database engine. See https://gorm.io/docs/connecting_to_the_database.html for more information.")
_ = Command.PersistentFlags().Bool(c.key+".skip-default-transaction", false, "disable the default transaction for single create, update, delete operations.")
_ = Command.PersistentFlags().Bool(c.key+".full-save-associations", false, "full save associations")
_ = Command.PersistentFlags().Bool(c.key+".dry-run", false, "generate sql without execute")
_ = Command.PersistentFlags().Bool(c.key+".prepare-stmt", false, "executes the given query in cached statement")
_ = Command.PersistentFlags().Bool(c.key+".disable-automatic-ping", false, "is used to disable the automatic ping to the database server")
_ = Command.PersistentFlags().Bool(c.key+".disable-foreign-key-constraint-when-migrating", false, "is used to disable the foreign key constraint when migrating the database")
_ = Command.PersistentFlags().Bool(c.key+".disable-nested-transaction", false, "disable nested transaction")
_ = Command.PersistentFlags().Bool(c.key+".allow-global-update", false, "allow global update")
_ = Command.PersistentFlags().Bool(c.key+".query-fields", false, "executes the SQL query with all fields of the table")
_ = Command.PersistentFlags().Int(c.key+".create-batch-size", 0, "default create batch size")
_ = Command.PersistentFlags().Bool(c.key+".enable-connection-pool", false, "is used to create a connection pool")
_ = Command.PersistentFlags().Int(c.key+".pool-max-idle-conns", 0, "sets the maximum number of connections idle in the connection pool if enable")
_ = Command.PersistentFlags().Int(c.key+".pool-max-open-conns", 0, "sets the maximum number of connections open in the connection pool if enable")
_ = Command.PersistentFlags().Duration(c.key+".pool-conn-max-lifetime", 5*time.Minute, "sets the maximum lifetime of connections in the connection pool if enable")
_ = Command.PersistentFlags().Bool(c.key+".disabled", false, "allow to disable a database connection without clean his configuration")
if err := Viper.BindPFlag(c.key+".driver", Command.PersistentFlags().Lookup(c.key+".driver")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".name", Command.PersistentFlags().Lookup(c.key+".name")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".dsn", Command.PersistentFlags().Lookup(c.key+".dsn")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".skip-default-transaction", Command.PersistentFlags().Lookup(c.key+".skip-default-transaction")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".full-save-associations", Command.PersistentFlags().Lookup(c.key+".full-save-associations")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".dry-run", Command.PersistentFlags().Lookup(c.key+".dry-run")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".prepare-stmt", Command.PersistentFlags().Lookup(c.key+".prepare-stmt")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".disable-automatic-ping", Command.PersistentFlags().Lookup(c.key+".disable-automatic-ping")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".disable-foreign-key-constraint-when-migrating", Command.PersistentFlags().Lookup(c.key+".disable-foreign-key-constraint-when-migrating")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".disable-nested-transaction", Command.PersistentFlags().Lookup(c.key+".disable-nested-transaction")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".allow-global-update", Command.PersistentFlags().Lookup(c.key+".allow-global-update")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".query-fields", Command.PersistentFlags().Lookup(c.key+".query-fields")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".create-batch-size", Command.PersistentFlags().Lookup(c.key+".create-batch-size")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".enable-connection-pool", Command.PersistentFlags().Lookup(c.key+".enable-connection-pool")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".pool-max-idle-conns", Command.PersistentFlags().Lookup(c.key+".pool-max-idle-conns")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".pool-max-open-conns", Command.PersistentFlags().Lookup(c.key+".pool-max-open-conns")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".pool-conn-max-lifetime", Command.PersistentFlags().Lookup(c.key+".pool-conn-max-lifetime")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".disabled", Command.PersistentFlags().Lookup(c.key+".disabled")); err != nil {
return err
} else if err = libsts.RegisterFlag(c.key+".status", Command, Viper); err != nil {
return err
}
return nil
}
func (c *componentDatabase) _getConfig(getCfg libcfg.FuncComponentConfigGet) (libdbs.Config, liberr.Error) {
var (
cnf = libdbs.Config{}
vpr = c.vpr()
)
if !c._CheckDep() {
return cnf, ErrorComponentNotInitialized.Error(nil)
}
if err := getCfg(c.key, &cnf); err != nil {
return cnf, ErrorParamInvalid.Error(err)
}
fct := func() liblog.Logger {
if l, e := c._GetLogger(); e != nil {
return liblog.GetDefault()
} else {
return l
}
}
cnf.RegisterLogger(fct, c.li, c.ls)
cnf.RegisterContext(c.ctx)
if val := vpr.GetString(c.key + ".driver"); val != "" {
cnf.Driver = libdbs.DriverFromString(val)
}
if val := vpr.GetString(c.key + ".name"); val != "" {
cnf.Name = val
}
if val := vpr.GetString(c.key + ".dsn"); val != "" {
cnf.DSN = val
}
if val := vpr.GetBool(c.key + ".skip-default-transaction"); val {
cnf.SkipDefaultTransaction = true
}
if val := vpr.GetBool(c.key + ".full-save-associations"); val {
cnf.FullSaveAssociations = true
}
if val := vpr.GetBool(c.key + ".dry-run"); val {
cnf.DryRun = true
}
if val := vpr.GetBool(c.key + ".prepare-stmt"); val {
cnf.PrepareStmt = true
}
if val := vpr.GetBool(c.key + ".disable-automatic-ping"); val {
cnf.DisableAutomaticPing = true
}
if val := vpr.GetBool(c.key + ".disable-foreign-key-constraint-when-migrating"); val {
cnf.DisableForeignKeyConstraintWhenMigrating = true
}
if val := vpr.GetBool(c.key + ".disable-nested-transaction"); val {
cnf.DisableNestedTransaction = true
}
if val := vpr.GetBool(c.key + ".allow-global-update"); val {
cnf.AllowGlobalUpdate = true
}
if val := vpr.GetBool(c.key + ".query-fields"); val {
cnf.QueryFields = true
}
if val := vpr.GetInt(c.key + ".create-batch-size"); val != 0 {
cnf.CreateBatchSize = val
}
if val := vpr.GetBool(c.key + ".enable-connection-pool"); val {
cnf.EnableConnectionPool = true
}
if val := vpr.GetInt(c.key + ".pool-max-idle-conns"); val != 0 {
cnf.PoolMaxIdleConns = val
}
if val := vpr.GetInt(c.key + ".pool-max-open-conns"); val != 0 {
cnf.PoolMaxOpenConns = val
}
if val := vpr.GetDuration(c.key + ".pool-conn-max-lifetime"); val != 0 {
cnf.PoolConnMaxLifetime = val
}
if val := vpr.GetBool(c.key + ".disabled"); val {
cnf.Disabled = true
}
if err := cnf.Validate(); err != nil {
return cnf, ErrorConfigInvalid.Error(err)
}
return cnf, nil
}

View File

@@ -38,8 +38,8 @@ const (
ErrorParamInvalid
ErrorComponentNotInitialized
ErrorConfigInvalid
ErrorStartDatabase
ErrorReloadDatabase
ErrorComponentStart
ErrorComponentReload
ErrorDependencyLogDefault
)
@@ -60,9 +60,9 @@ func getMessage(code liberr.CodeError) (message string) {
return "this component seems to not be correctly initialized"
case ErrorConfigInvalid:
return "server invalid config"
case ErrorStartDatabase:
case ErrorComponentStart:
return "cannot open database connection with config"
case ErrorReloadDatabase:
case ErrorComponentReload:
return "cannot update database connection with new config"
case ErrorDependencyLogDefault:
return "cannot retrieve default Logger"

View File

@@ -31,27 +31,26 @@ import (
"time"
libcfg "github.com/nabbar/golib/config"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
libdbs "github.com/nabbar/golib/database"
)
const (
ComponentType = "database"
)
type ComponentDatabase interface {
libcfg.Component
cfgtps.Component
SetLOGKey(logKey string)
SetLogOptions(ignoreRecordNotFoundError bool, slowThreshold time.Duration)
GetDatabase() libdbs.Database
SetDatabase(db libdbs.Database)
}
func New(logKey string) ComponentDatabase {
func New(ctx libctx.FuncContext) ComponentDatabase {
return &componentDatabase{
m: sync.Mutex{},
l: logKey,
d: nil,
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
li: false,
ls: 0,
d: nil,
}
}
@@ -59,11 +58,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentDatabase) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key, logKey string) {
cfg.ComponentSet(key, New(logKey))
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New(ctx))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentDatabase {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentDatabase {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentDatabase); !ok {

View File

@@ -30,212 +30,38 @@ import (
"sync"
"time"
libcfg "github.com/nabbar/golib/config"
cptlog "github.com/nabbar/golib/config/components/log"
libctx "github.com/nabbar/golib/context"
libdbs "github.com/nabbar/golib/database"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
montps "github.com/nabbar/golib/monitor/types"
)
type componentDatabase struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
l string
m sync.RWMutex
x libctx.Config[uint8]
li bool
ls time.Duration
d libdbs.Database
p montps.FuncPool
}
func (c *componentDatabase) _CheckDep() bool {
return c != nil && c.l != ""
func (o *componentDatabase) SetLogOptions(ignoreRecordNotFoundError bool, slowThreshold time.Duration) {
o.m.Lock()
defer o.m.Unlock()
o.li = ignoreRecordNotFoundError
o.ls = slowThreshold
}
func (c *componentDatabase) _GetLogger() (liblog.Logger, liberr.Error) {
if !c._CheckDep() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
func (o *componentDatabase) SetDatabase(db libdbs.Database) {
o.m.Lock()
defer o.m.Unlock()
if i := cptlog.Load(c.get, c.l); i == nil {
return nil, ErrorDependencyLogDefault.Error(nil)
} else if log := i.Log(); log == nil {
return nil, ErrorDependencyLogDefault.Error(nil)
} else {
return log, nil
}
o.d = db
}
func (c *componentDatabase) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
var isReload = c.IsStarted()
func (o *componentDatabase) GetDatabase() libdbs.Database {
o.m.RLock()
defer o.m.RUnlock()
c.m.Lock()
defer c.m.Unlock()
if isReload {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentDatabase) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentDatabase) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
var (
err liberr.Error
cnf libdbs.Config
)
if cnf, err = c._getConfig(getCfg); err != nil {
return err
}
if c.d != nil {
c.d.Close()
}
if c.d, err = libdbs.New(&cnf); err != nil {
return ErrorStartDatabase.Error(err)
}
return nil
}
func (c *componentDatabase) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
if !c._CheckDep() {
return ErrorComponentNotInitialized.Error(nil)
}
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentDatabase) Type() string {
return ComponentType
}
func (c *componentDatabase) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentDatabase) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentDatabase) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentDatabase) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
if c == nil || c.d == nil {
return false
}
if db := c.GetDatabase(); db == nil {
return false
} else if e := db.CheckConn(); e != nil {
return false
}
return true
}
func (c *componentDatabase) IsRunning(atLeast bool) bool {
return c.IsStarted()
}
func (c *componentDatabase) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentDatabase) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentDatabase) Stop() {
if db := c.GetDatabase(); db != nil {
db.Close()
}
}
func (c *componentDatabase) Dependencies() []string {
if c == nil {
return []string{cptlog.ComponentType}
}
c.m.Lock()
defer c.m.Unlock()
return []string{c.l}
}
func (c *componentDatabase) SetLOGKey(logKey string) {
c.m.Lock()
defer c.m.Unlock()
c.l = logKey
}
func (c *componentDatabase) SetLogOptions(ignoreRecordNotFoundError bool, slowThreshold time.Duration) {
c.m.Lock()
defer c.m.Unlock()
c.li = ignoreRecordNotFoundError
c.ls = slowThreshold
}
func (c *componentDatabase) SetDatabase(db libdbs.Database) {
c.m.Lock()
defer c.m.Unlock()
c.d = db
}
func (c *componentDatabase) GetDatabase() libdbs.Database {
c.m.Lock()
defer c.m.Unlock()
return c.d
return o.d
}

View File

@@ -0,0 +1,133 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package database
import (
libdbs "github.com/nabbar/golib/database"
libmon "github.com/nabbar/golib/monitor"
montps "github.com/nabbar/golib/monitor/types"
libver "github.com/nabbar/golib/version"
)
func (o *componentDatabase) RegisterMonitorPool(fct montps.FuncPool) {
o.m.Lock()
defer o.m.Unlock()
o.p = fct
}
func (o *componentDatabase) _getMonitorPool() montps.Pool {
o.m.RLock()
defer o.m.RUnlock()
if o.p == nil {
return nil
} else if p := o.p(); p == nil {
return nil
} else {
return p
}
}
func (o *componentDatabase) _registerMonitor(cfg *libdbs.Config) error {
var (
e error
key = o._getKey()
mon libmon.Monitor
vrs = o._getVersion()
)
if o._getMonitorPool() == nil {
return nil
} else if len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
} else if cfg == nil {
return ErrorConfigInvalid.Error(nil)
} else if !o.IsStarted() {
return ErrorComponentStart.Error(nil)
}
if mon = o._getMonitor(key); mon == nil {
if mon, e = o._newMonitor(vrs); e != nil {
return e
} else if mon == nil {
return nil
}
}
if e = mon.SetConfig(o.x.GetContext, cfg.Monitor); e != nil {
return e
}
if e = mon.Restart(o.x.GetContext()); e != nil {
return e
} else if e = o._setMonitor(mon); e != nil {
return e
}
return nil
}
func (o *componentDatabase) _newMonitor(vrs libver.Version) (libmon.Monitor, error) {
o.m.RLock()
defer o.m.RUnlock()
if c, e := o.d.Monitor(vrs); e != nil {
return nil, e
} else {
c.RegisterLoggerDefault(o.getLogger)
return c, nil
}
}
func (o *componentDatabase) _getMonitor(key string) libmon.Monitor {
var (
mon libmon.Monitor
pol = o._getMonitorPool()
)
if pol == nil {
return nil
}
mon = pol.MonitorGet(key)
if mon != nil {
mon.RegisterLoggerDefault(o.getLogger)
}
return mon
}
func (o *componentDatabase) _setMonitor(mon libmon.Monitor) error {
var pol = o._getMonitorPool()
if pol == nil {
return nil
}
return pol.MonitorSet(mon)
}

View File

@@ -0,0 +1,172 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package head
import (
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentHead) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentHead) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentHead) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentHead) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentHead) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentHead) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentHead) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentHead) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentHead) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentHead) _runCli() liberr.Error {
if cfg, err := o._getConfig(); err != nil {
return ErrorParamInvalid.Error(err)
} else {
o.m.Lock()
defer o.m.Unlock()
o.h = cfg.New()
return nil
}
}
func (o *componentHead) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,155 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package head
import (
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "head"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentHead) Type() string {
return ComponentType
}
func (o *componentHead) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentHead) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentHead) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentHead) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o.h != nil
}
func (o *componentHead) IsRunning() bool {
return o.IsStarted()
}
func (o *componentHead) Start() liberr.Error {
return o._run()
}
func (o *componentHead) Reload() liberr.Error {
return o._run()
}
func (o *componentHead) Stop() {
o.m.Lock()
defer o.m.Unlock()
o.h = nil
return
}
func (o *componentHead) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = make([]string, 0)
if o == nil {
return def
} else if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentHead) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentHead) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,63 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package head
import (
liberr "github.com/nabbar/golib/errors"
librtr "github.com/nabbar/golib/router"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentHead) RegisterFlag(Command *spfcbr.Command) error {
return nil
}
func (o *componentHead) _getConfig() (*librtr.HeadersConfig, liberr.Error) {
var (
key string
cfg librtr.HeadersConfig
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -30,9 +30,7 @@ import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgcst "github.com/nabbar/golib/config/const"
)
var _defaultConfig = []byte(`{
@@ -51,17 +49,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentHead) DefaultConfig(indent string) []byte {
func (o *componentHead) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentHead) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
return nil
}

View File

@@ -27,16 +27,15 @@
package head
import (
"sync"
libcfg "github.com/nabbar/golib/config"
cfgtps "github.com/nabbar/golib/config/types"
librtr "github.com/nabbar/golib/router"
)
const (
ComponentType = "head"
)
type ComponentHead interface {
libcfg.Component
cfgtps.Component
GetHeaders() librtr.Headers
SetHeaders(head librtr.Headers)
@@ -44,6 +43,7 @@ type ComponentHead interface {
func New() ComponentHead {
return &componentHead{
m: sync.RWMutex{},
h: nil,
}
}
@@ -56,7 +56,7 @@ func RegisterNew(cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New())
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentHead {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentHead {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentHead); !ok {

View File

@@ -29,139 +29,26 @@ package head
import (
"sync"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
libctx "github.com/nabbar/golib/context"
librtr "github.com/nabbar/golib/router"
)
type componentHead struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
m sync.RWMutex
x libctx.Config[uint8]
h librtr.Headers
}
func (c *componentHead) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
func (o *componentHead) GetHeaders() librtr.Headers {
o.m.RLock()
defer o.m.RUnlock()
if c.h != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
return o.h
}
func (c *componentHead) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
func (o *componentHead) SetHeaders(head librtr.Headers) {
o.m.Lock()
defer o.m.Unlock()
return nil
}
func (c *componentHead) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
cnf := librtr.HeadersConfig{}
if err := getCfg(c.key, &cnf); err != nil {
return ErrorParamInvalid.Error(err)
}
c.h = cnf.New()
return nil
}
func (c *componentHead) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentHead) Type() string {
return ComponentType
}
func (c *componentHead) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentHead) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentHead) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentHead) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c.h != nil
}
func (c *componentHead) IsRunning(atLeast bool) bool {
return c.IsStarted()
}
func (c *componentHead) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentHead) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentHead) Stop() {
}
func (c *componentHead) Dependencies() []string {
return []string{}
}
func (c *componentHead) GetHeaders() librtr.Headers {
c.m.Lock()
defer c.m.Unlock()
return c.h
}
func (c *componentHead) SetHeaders(head librtr.Headers) {
c.m.Lock()
defer c.m.Unlock()
c.h = head
o.h = head
}

View File

@@ -0,0 +1,34 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package head
import (
montps "github.com/nabbar/golib/monitor/types"
)
func (o *componentHead) RegisterMonitorPool(fct montps.FuncPool) {
}

View File

@@ -0,0 +1,248 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package http
import (
"context"
"net/http"
libtls "github.com/nabbar/golib/certificates"
cpttls "github.com/nabbar/golib/config/components/tls"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
htpool "github.com/nabbar/golib/httpserver/pool"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentHttp) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentHttp) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentHttp) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentHttp) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentHttp) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentHttp) _getContext() context.Context {
o.m.RLock()
defer o.m.RUnlock()
return o.x.GetContext()
}
func (o *componentHttp) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentHttp) _GetTLS() libtls.TLSConfig {
o.m.RLock()
defer o.m.RUnlock()
if o.t == "" {
return nil
}
if i := cpttls.Load(o._getFctCpt(), o.t); i == nil {
return nil
} else if tls := i.GetTLS(); tls == nil {
return nil
} else {
return tls
}
}
func (o *componentHttp) _GetHandler() map[string]http.Handler {
o.m.RLock()
defer o.m.RUnlock()
if o.h == nil {
return nil
} else {
return o.h()
}
}
func (o *componentHttp) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentHttp) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentHttp) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentHttp) _runCli() liberr.Error {
var (
e error
err liberr.Error
prt = ErrorComponentReload
pol htpool.Pool
cfg *htpool.Config
)
if !o.IsStarted() {
prt = ErrorComponentStart
}
if cfg, err = o._getConfig(); err != nil {
return prt.Error(err)
}
o.m.RLock()
defer o.m.RUnlock()
if pol, err = cfg.Pool(o.x.GetContext, o._GetHandler, o.getLogger); err != nil {
return prt.ErrorParent(err)
}
if o.s != nil && o.s.Len() > 0 {
if e = o.s.Merge(pol, o.getLogger); e != nil {
return prt.ErrorParent(e)
}
} else {
o.m.RUnlock()
o.m.Lock()
o.s = pol
o.m.Unlock()
o.m.RLock()
}
if e = o.s.Restart(o.x.GetContext()); e != nil {
return prt.ErrorParent(e)
}
// Implement wait notify on main call
//o.s.StopWaitNotify()
//o.s.StartWaitNotify(o.x.GetContext())
return o._registerMonitor(prt)
}
func (o *componentHttp) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,168 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package http
import (
cpttls "github.com/nabbar/golib/config/components/tls"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "http"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentHttp) Type() string {
return ComponentType
}
func (o *componentHttp) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentHttp) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentHttp) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentHttp) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o != nil && o.s != nil && o.t != "" && o.h != nil
}
func (o *componentHttp) IsRunning() bool {
if !o.IsStarted() {
return false
}
o.m.RLock()
defer o.m.RUnlock()
return o.s.IsRunning()
}
func (o *componentHttp) Start() liberr.Error {
return o._run()
}
func (o *componentHttp) Reload() liberr.Error {
return o._run()
}
func (o *componentHttp) Stop() {
o.m.Lock()
defer o.m.Unlock()
_ = o.s.Stop(o.x.GetContext())
o.s = nil
return
}
func (o *componentHttp) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = []string{cpttls.ComponentType}
if o == nil {
return def
} else if len(o.t) > 0 {
def = []string{o.t}
}
if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentHttp) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentHttp) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -24,64 +24,50 @@
*
*/
package nutsdb
package http
import (
"sync"
"time"
"fmt"
libcfg "github.com/nabbar/golib/config"
cptlog "github.com/nabbar/golib/config/components/log"
liberr "github.com/nabbar/golib/errors"
libndb "github.com/nabbar/golib/nutsdb"
libsts "github.com/nabbar/golib/status"
htpool "github.com/nabbar/golib/httpserver/pool"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
const (
ComponentType = "nutsdb"
)
type ComponentNutsDB interface {
libcfg.Component
SetLogger(key string)
GetServer() (libndb.NutsDB, liberr.Error)
GetClient(tickSync time.Duration) (libndb.Client, liberr.Error)
SetStatusRouter(sts libsts.RouteStatus, prefix string)
func (o *componentHttp) RegisterFlag(Command *spfcbr.Command) error {
return nil
}
func New(logKey string) ComponentNutsDB {
if logKey == "" {
logKey = cptlog.ComponentType
func (o *componentHttp) _getConfig() (*htpool.Config, liberr.Error) {
var (
key string
cfg htpool.Config
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
return &componentNutsDB{
ctx: nil,
get: nil,
fsa: nil,
fsb: nil,
fra: nil,
frb: nil,
m: sync.Mutex{},
l: logKey,
n: nil,
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
}
func Register(cfg libcfg.Config, key string, cpt ComponentNutsDB) {
cfg.ComponentSet(key, cpt)
}
cfg.SetDefaultTLS(o._GetTLS)
cfg.SetContext(o.x.GetContext)
cfg.SetHandlerFunc(o._GetHandler)
func RegisterNew(cfg libcfg.Config, key, logKey string) {
cfg.ComponentSet(key, New(logKey))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentNutsDB {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentNutsDB); !ok {
return nil
} else {
return h
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
} else if o.h == nil {
return nil, ErrorComponentNotInitialized.ErrorParent(fmt.Errorf("missing handler"))
} else if len(o.h()) < 1 {
return nil, ErrorComponentNotInitialized.ErrorParent(fmt.Errorf("missing handler"))
}
return &cfg, nil
}

View File

@@ -30,21 +30,20 @@ import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
cpttls "github.com/nabbar/golib/config/components/tls"
libsts "github.com/nabbar/golib/status/config"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgcst "github.com/nabbar/golib/config/const"
cptlog "github.com/nabbar/golib/logger/config"
moncfg "github.com/nabbar/golib/monitor/types"
)
var _defaultConfig = []byte(`[
{
"disabled":false,
"name":"status_http",
"handler_keys":"status",
"handler_key":"status",
"listen":"0.0.0.0:6080",
"expose":"http://0.0.0.0",
"status":` + string(libsts.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `,
"monitor":` + string(moncfg.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"read_timeout":"0s",
"read_header_timeout":"0s",
"write_timeout":"0s",
@@ -57,15 +56,16 @@ var _defaultConfig = []byte(`[
"max_upload_buffer_per_connection":0,
"max_upload_buffer_per_stream":0,
"tls_mandatory":false,
"tls": ` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
"tls":` + string(cpttls.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"logger":` + string(cptlog.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `
},
{
"disabled":false,
"name":"api_http",
"handler_keys":"api",
"handler_key":"api",
"listen":"0.0.0.0:7080",
"expose":"http://0.0.0.0",
"status":` + string(libsts.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `,
"monitor":` + string(moncfg.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"read_timeout":"0s",
"read_header_timeout":"0s",
"write_timeout":"0s",
@@ -78,15 +78,16 @@ var _defaultConfig = []byte(`[
"max_upload_buffer_per_connection":0,
"max_upload_buffer_per_stream":0,
"tls_mandatory":false,
"tls":` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
"tls":` + string(cpttls.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"logger":` + string(cptlog.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `
},
{
"disabled":false,
"name":"metrics_http",
"handler_keys":"metrics",
"handler_key":"metrics",
"listen":"0.0.0.0:8080",
"expose":"http://0.0.0.0",
"status":` + string(libsts.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `,
"monitor":` + string(moncfg.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"read_timeout":"0s",
"read_header_timeout":"0s",
"write_timeout":"0s",
@@ -99,7 +100,8 @@ var _defaultConfig = []byte(`[
"max_upload_buffer_per_connection":0,
"max_upload_buffer_per_stream":0,
"tls_mandatory":false,
"tls":` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
"tls":` + string(cpttls.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
"logger":` + string(cptlog.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `
}
]`)
@@ -109,17 +111,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentHttp) DefaultConfig(indent string) []byte {
func (o *componentHttp) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentHttp) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
return nil
}

View File

@@ -38,10 +38,9 @@ const (
ErrorParamInvalid
ErrorComponentNotInitialized
ErrorConfigInvalid
ErrorStartComponent
ErrorReloadComponent
ErrorComponentStart
ErrorComponentReload
ErrorDependencyTLSDefault
ErrorDependencyLogDefault
)
func init() {
@@ -61,14 +60,12 @@ func getMessage(code liberr.CodeError) (message string) {
return "this component seems to not be correctly initialized"
case ErrorConfigInvalid:
return "invalid component config"
case ErrorStartComponent:
case ErrorComponentStart:
return "cannot start component with config"
case ErrorReloadComponent:
case ErrorComponentReload:
return "cannot reload component with new config"
case ErrorDependencyTLSDefault:
return "cannot retrieve TLS component"
case ErrorDependencyLogDefault:
return "cannot retrieve Logger Component"
}
return liberr.NullMessage

View File

@@ -27,46 +27,41 @@
package http
import (
"net/http"
"sync"
libcfg "github.com/nabbar/golib/config"
libhts "github.com/nabbar/golib/httpserver"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
htpool "github.com/nabbar/golib/httpserver/pool"
srvtps "github.com/nabbar/golib/httpserver/types"
)
const (
DefaultTlsKey = "tls"
DefaultLogKey = "log"
ComponentType = "http"
DefaultTlsKey = "t"
)
type ComponentHttp interface {
libcfg.Component
cfgtps.Component
SetTLSKey(tlsKey string)
SetLOGKey(logKey string)
SetHandler(handler map[string]http.Handler)
SetHandler(fct srvtps.FuncHandler)
GetPool() libhts.PoolServer
SetPool(pool libhts.PoolServer)
GetPool() htpool.Pool
SetPool(pool htpool.Pool)
}
func New(tlsKey, logKey string, handler map[string]http.Handler) ComponentHttp {
func New(ctx libctx.FuncContext, tlsKey string, hdl srvtps.FuncHandler) ComponentHttp {
if tlsKey == "" {
tlsKey = DefaultTlsKey
}
if logKey == "" {
logKey = DefaultLogKey
}
return &componentHttp{
m: sync.Mutex{},
tls: tlsKey,
log: logKey,
run: false,
hand: handler,
pool: nil,
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
t: tlsKey,
h: hdl,
s: nil,
p: nil,
}
}
@@ -74,11 +69,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentHttp) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key string, tlsKey, logKey string, handler map[string]http.Handler) {
cfg.ComponentSet(key, New(tlsKey, logKey, handler))
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string, tlsKey string, hdl srvtps.FuncHandler) {
cfg.ComponentSet(key, New(ctx, tlsKey, hdl))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentHttp {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentHttp {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentHttp); !ok {

View File

@@ -27,302 +27,48 @@
package http
import (
"fmt"
"net/http"
"sync"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
cptlog "github.com/nabbar/golib/config/components/log"
cpttls "github.com/nabbar/golib/config/components/tls"
liberr "github.com/nabbar/golib/errors"
libhts "github.com/nabbar/golib/httpserver"
liblog "github.com/nabbar/golib/logger"
libctx "github.com/nabbar/golib/context"
htpool "github.com/nabbar/golib/httpserver/pool"
srvtps "github.com/nabbar/golib/httpserver/types"
montps "github.com/nabbar/golib/monitor/types"
)
type componentHttp struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
sts libcfg.FuncRouteStatus
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
tls string
log string
run bool
hand map[string]http.Handler
pool libhts.PoolServer
m sync.RWMutex
x libctx.Config[uint8]
r bool
t string
h srvtps.FuncHandler
s htpool.Pool
p montps.FuncPool
}
func (c *componentHttp) _CheckDep() bool {
return c != nil && len(c.hand) > 0 && c.tls != "" && c.log != ""
func (o *componentHttp) SetTLSKey(tlsKey string) {
o.m.Lock()
defer o.m.Unlock()
o.t = tlsKey
}
func (c *componentHttp) _CheckInit() bool {
return c != nil && c._CheckDep() && c.pool != nil
func (o *componentHttp) SetHandler(fct srvtps.FuncHandler) {
o.m.Lock()
defer o.m.Unlock()
o.h = fct
}
func (c *componentHttp) _GetTLS() (libtls.TLSConfig, liberr.Error) {
if !c._CheckDep() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
func (o *componentHttp) GetPool() htpool.Pool {
o.m.Lock()
defer o.m.Unlock()
if i := cpttls.Load(c.get, c.tls); i == nil {
return nil, ErrorDependencyTLSDefault.Error(nil)
} else if tls := i.GetTLS(); tls == nil {
return nil, ErrorDependencyTLSDefault.Error(nil)
} else {
return tls, nil
}
return o.s
}
func (c *componentHttp) _GetLogger() (liblog.Logger, liberr.Error) {
if !c._CheckDep() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
func (o *componentHttp) SetPool(pool htpool.Pool) {
o.m.Lock()
defer o.m.Unlock()
if i := cptlog.Load(c.get, c.log); i == nil {
return nil, ErrorDependencyLogDefault.Error(nil)
} else if log := i.Log(); log == nil {
return nil, ErrorDependencyLogDefault.Error(nil)
} else {
return log, nil
}
}
func (c *componentHttp) _getPoolServerConfig(getCfg libcfg.FuncComponentConfigGet) (libhts.PoolServerConfig, liberr.Error) {
cnf := make(libhts.PoolServerConfig, 0)
if !c._CheckDep() {
return cnf, ErrorComponentNotInitialized.Error(nil)
}
if err := getCfg(c.key, &cnf); err != nil {
return cnf, ErrorParamInvalid.Error(err)
}
if tls, err := c._GetTLS(); err != nil {
return cnf, err
} else {
cnf.MapUpdate(func(sCFG libhts.ServerConfig) libhts.ServerConfig {
sCFG.SetDefaultTLS(func() libtls.TLSConfig {
return tls
})
sCFG.SetParentContext(c.ctx)
return sCFG
})
}
if err := cnf.Validate(); err != nil {
return cnf, ErrorConfigInvalid.Error(err)
} else if len(c.hand) < 1 {
return cnf, ErrorComponentNotInitialized.ErrorParent(fmt.Errorf("missing handler"))
}
return cnf, nil
}
func (c *componentHttp) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
var isReload = c.IsStarted()
c.m.Lock()
defer c.m.Unlock()
if isReload {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentHttp) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentHttp) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
var (
err liberr.Error
cnf libhts.PoolServerConfig
)
if cnf, err = c._getPoolServerConfig(getCfg); err != nil {
return err
}
if c.pool != nil {
if p, e := cnf.UpdatePoolServer(c.pool); e != nil {
return ErrorReloadComponent.Error(e)
} else {
c.pool = p
}
} else if p, e := cnf.PoolServer(); e != nil {
return ErrorReloadComponent.Error(e)
} else {
c.pool = p
}
c.pool.SetLogger(func() liblog.Logger {
var (
l liblog.Logger
e liberr.Error
)
if l, e = c._GetLogger(); e != nil {
return liblog.GetDefault()
} else {
return l
}
})
if c.sts != nil {
c.pool.StatusRoute(c.key, c.sts())
}
if err = c.pool.ListenMultiHandler(c.hand); err != nil {
return ErrorStartComponent.Error(err)
}
return nil
}
func (c *componentHttp) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
if !c._CheckDep() {
return ErrorComponentNotInitialized.Error(nil)
}
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentHttp) Type() string {
return ComponentType
}
func (c *componentHttp) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
c.sts = sts
}
func (c *componentHttp) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentHttp) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentHttp) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c._CheckInit() && c.pool.IsRunning(true)
}
func (c *componentHttp) IsRunning(atLeast bool) bool {
c.m.Lock()
defer c.m.Unlock()
return c._CheckInit() && c.pool.IsRunning(atLeast)
}
func (c *componentHttp) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentHttp) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentHttp) Stop() {
c.m.Lock()
defer c.m.Unlock()
if c._CheckInit() {
c.pool.Shutdown()
}
}
func (c *componentHttp) Dependencies() []string {
c.m.Lock()
defer c.m.Unlock()
if !c._CheckDep() {
return []string{cpttls.ComponentType, cptlog.ComponentType}
}
return []string{c.tls, c.log}
}
func (c *componentHttp) SetTLSKey(tlsKey string) {
c.m.Lock()
defer c.m.Unlock()
c.tls = tlsKey
}
func (c *componentHttp) SetLOGKey(logKey string) {
c.m.Lock()
defer c.m.Unlock()
c.log = logKey
}
func (c *componentHttp) SetHandler(handler map[string]http.Handler) {
c.m.Lock()
defer c.m.Unlock()
c.hand = handler
}
func (c *componentHttp) GetPool() libhts.PoolServer {
c.m.Lock()
defer c.m.Unlock()
return c.pool
}
func (c *componentHttp) SetPool(pool libhts.PoolServer) {
c.m.Lock()
defer c.m.Unlock()
c.pool = pool
o.s = pool
}

View File

@@ -0,0 +1,139 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package http
import (
liberr "github.com/nabbar/golib/errors"
montps "github.com/nabbar/golib/monitor/types"
libver "github.com/nabbar/golib/version"
)
func (o *componentHttp) RegisterMonitorPool(fct montps.FuncPool) {
o.m.Lock()
defer o.m.Unlock()
o.p = fct
}
func (o *componentHttp) _getMonitorPool() montps.Pool {
o.m.RLock()
defer o.m.RUnlock()
if o.p == nil {
return nil
} else if p := o.p(); p == nil {
return nil
} else {
return p
}
}
func (o *componentHttp) _registerMonitor(err liberr.CodeError) liberr.Error {
var (
e error
key = o._getKey()
mon []montps.Monitor
vrs = o._getVersion()
ctx = o.x.GetContext
)
if o._getMonitorPool() == nil {
return nil
} else if len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
} else if !o.IsStarted() {
return ErrorComponentStart.Error(nil)
}
if mon, e = o._newMonitor(vrs); e != nil {
return err.ErrorParent(e)
} else if mon == nil {
return nil
}
for _, m := range mon {
if old := o._getMonitor(m.Name()); old != nil {
old.InfoUpd(m.InfoGet())
if e = old.SetConfig(ctx, m.GetConfig()); e == nil {
m = old
}
}
if e = m.Restart(ctx()); e != nil {
return err.ErrorParent(e)
} else if e = o._setMonitor(m); e != nil {
return err.ErrorParent(e)
}
}
return nil
}
func (o *componentHttp) _newMonitor(vrs libver.Version) ([]montps.Monitor, error) {
o.m.RLock()
defer o.m.RUnlock()
if c, e := o.s.Monitor(vrs); e != nil {
return nil, e
} else {
for k := range c {
if c[k] != nil {
c[k].RegisterLoggerDefault(o.getLogger)
}
}
return c, nil
}
}
func (o *componentHttp) _getMonitor(key string) montps.Monitor {
var (
mon montps.Monitor
pol = o._getMonitorPool()
)
if pol == nil {
return nil
}
mon = pol.MonitorGet(key)
if mon != nil {
mon.RegisterLoggerDefault(o.getLogger)
}
return mon
}
func (o *componentHttp) _setMonitor(mon montps.Monitor) error {
var pol = o._getMonitorPool()
if pol == nil {
return nil
}
return pol.MonitorSet(mon)
}

View File

@@ -0,0 +1,194 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package ldap
import (
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
lbldap "github.com/nabbar/golib/ldap"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentLDAP) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentLDAP) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentLDAP) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentLDAP) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentLDAP) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentLDAP) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentLDAP) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentLDAP) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentLDAP) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentLDAP) _runCli() liberr.Error {
var (
e error
err liberr.Error
cli *lbldap.HelperLDAP
cfg *lbldap.Config
)
o.m.RLock()
defer o.m.RUnlock()
if cfg, err = o._getConfig(); err != nil {
return ErrorParamInvalid.Error(err)
} else if cli, e = lbldap.NewLDAP(o.x.GetContext(), cfg, o.a); e != nil {
return ErrorConfigInvalid.ErrorParent(e)
} else {
cli.SetLogger(o.getLogger)
}
if o.l != nil {
o.l.Close()
}
o.m.RUnlock()
o.m.Lock()
o.l = cli
o.c = cfg
o.m.Unlock()
o.m.RLock()
return nil
}
func (o *componentLDAP) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,157 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package ldap
import (
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "LDAP"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentLDAP) Type() string {
return ComponentType
}
func (o *componentLDAP) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentLDAP) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentLDAP) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentLDAP) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o != nil && o.l != nil
}
func (o *componentLDAP) IsRunning() bool {
return o.IsStarted()
}
func (o *componentLDAP) Start() liberr.Error {
return o._run()
}
func (o *componentLDAP) Reload() liberr.Error {
return o._run()
}
func (o *componentLDAP) Stop() {
o.m.Lock()
defer o.m.Unlock()
o.l.Close()
o.l = nil
return
}
func (o *componentLDAP) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = make([]string, 0)
if o == nil {
return def
} else if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentLDAP) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentLDAP) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,63 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package ldap
import (
liberr "github.com/nabbar/golib/errors"
lbldap "github.com/nabbar/golib/ldap"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentLDAP) RegisterFlag(Command *spfcbr.Command) error {
return nil
}
func (o *componentLDAP) _getConfig() (*lbldap.Config, liberr.Error) {
var (
key string
cfg lbldap.Config
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -30,9 +30,7 @@ import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgcst "github.com/nabbar/golib/config/const"
)
var _defaultConfig = []byte(`{
@@ -50,17 +48,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentLDAP) DefaultConfig(indent string) []byte {
func (o *componentLDAP) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentLDAP) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
return nil
}

View File

@@ -30,25 +30,30 @@ import (
"sync"
libcfg "github.com/nabbar/golib/config"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
lbldap "github.com/nabbar/golib/ldap"
)
const (
ComponentType = "LDAP"
)
// @TODO: refactor LDAP Package
type ComponentLDAP interface {
libcfg.Component
cfgtps.Component
Config() *lbldap.Config
LDAP() *lbldap.HelperLDAP
SetAttributes(att []string)
GetConfig() *lbldap.Config
SetConfig(opt *lbldap.Config)
GetLDAP() *lbldap.HelperLDAP
SetLDAP(l *lbldap.HelperLDAP)
}
func New() ComponentLDAP {
func New(ctx libctx.FuncContext) ComponentLDAP {
return &componentLDAP{
m: sync.Mutex{},
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
c: nil,
l: nil,
}
}
@@ -57,11 +62,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentLDAP) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New())
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New(ctx))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentLDAP {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentLDAP {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentLDAP); !ok {

View File

@@ -27,173 +27,55 @@
package ldap
import (
"context"
"sync"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
libctx "github.com/nabbar/golib/context"
lbldap "github.com/nabbar/golib/ldap"
)
type componentLDAP struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
sts libcfg.FuncRouteStatus
key string
m sync.RWMutex
x libctx.Config[uint8]
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
a []string
c *lbldap.Config
l *lbldap.HelperLDAP
}
func (c *componentLDAP) _GetContext() context.Context {
c.m.Lock()
defer c.m.Unlock()
func (o *componentLDAP) GetConfig() *lbldap.Config {
o.m.RLock()
defer o.m.RUnlock()
if c.ctx != nil {
if x := c.ctx(); x != nil {
return x
}
}
return context.Background()
return o.c
}
func (c *componentLDAP) _CheckInit() bool {
return c != nil && c.l != nil
func (o *componentLDAP) SetConfig(opt *lbldap.Config) {
o.m.Lock()
defer o.m.Unlock()
o.c = opt
}
func (c *componentLDAP) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
func (o *componentLDAP) GetLDAP() *lbldap.HelperLDAP {
o.m.RLock()
defer o.m.RUnlock()
if c.l != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
return o.l
}
func (o *componentLDAP) SetLDAP(l *lbldap.HelperLDAP) {
o.m.Lock()
defer o.m.Unlock()
o.l = l
}
func (o *componentLDAP) SetAttributes(att []string) {
o.m.Lock()
defer o.m.Unlock()
o.a = att
if o.l != nil {
o.l.Attributes = att
}
}
func (c *componentLDAP) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentLDAP) _runCli(ctx context.Context, getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
cfg := lbldap.Config{}
if err := getCfg(c.key, &cfg); err != nil {
return ErrorParamInvalid.Error(err)
}
if l, e := lbldap.NewLDAP(ctx, &cfg, nil); e != nil {
return ErrorConfigInvalid.ErrorParent(e)
} else {
c.l = l
c.c = &cfg
}
if c.sts != nil {
if s := c.sts(); s != nil {
}
}
return nil
}
func (c *componentLDAP) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(c._GetContext(), getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentLDAP) Type() string {
return ComponentType
}
func (c *componentLDAP) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentLDAP) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentLDAP) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentLDAP) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c != nil && c.l != nil
}
func (c *componentLDAP) IsRunning(atLeast bool) bool {
return c.IsStarted()
}
func (c *componentLDAP) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentLDAP) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentLDAP) Stop() {
}
func (c *componentLDAP) Dependencies() []string {
return make([]string, 0)
}
func (c *componentLDAP) Config() *lbldap.Config {
c.m.Lock()
defer c.m.Unlock()
return c.c
}
func (c *componentLDAP) LDAP() *lbldap.HelperLDAP {
c.m.Lock()
defer c.m.Unlock()
return c.l
}

View File

@@ -0,0 +1,34 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package ldap
import (
montps "github.com/nabbar/golib/monitor/types"
)
func (o *componentLDAP) RegisterMonitorPool(fct montps.FuncPool) {
}

View File

@@ -0,0 +1,194 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package log
import (
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentLog) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentLog) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentLog) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentLog) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentLog) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentLog) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentLog) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentLog) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentLog) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentLog) _runCli() liberr.Error {
var (
e error
err liberr.Error
prt = ErrorReloadLog
cfg *liblog.Options
)
if !o.IsStarted() {
prt = ErrorStartLog
o.m.Lock()
o.l = liblog.New(o.x.GetContext)
o.l.SetLevel(o.v)
o.m.Unlock()
}
if cfg, err = o._getConfig(); err != nil {
return ErrorParamInvalid.Error(err)
}
o.m.RLock()
defer o.m.RUnlock()
if e = o.l.SetOptions(cfg); e != nil {
return prt.ErrorParent(e)
}
return nil
}
func (o *componentLog) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,156 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package log
import (
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "head"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentLog) Type() string {
return ComponentType
}
func (o *componentLog) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentLog) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentLog) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentLog) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o.l != nil
}
func (o *componentLog) IsRunning() bool {
return o.IsStarted()
}
func (o *componentLog) Start() liberr.Error {
return o._run()
}
func (o *componentLog) Reload() liberr.Error {
return o._run()
}
func (o *componentLog) Stop() {
o.m.Lock()
defer o.m.Unlock()
_ = o.l.Close()
o.l = nil
return
}
func (o *componentLog) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = make([]string, 0)
if o == nil {
return def
} else if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentLog) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentLog) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,120 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package log
import (
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentLog) RegisterFlag(Command *spfcbr.Command) error {
var (
key string
vpr *spfvpr.Viper
err error
)
if vpr = o._getSPFViper(); vpr == nil {
return ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
}
_ = Command.PersistentFlags().Bool(key+".disableStandard", false, "allow disabling to write log to standard output stdout/stderr.")
_ = Command.PersistentFlags().Bool(key+".disableStack", false, "allow to disable the goroutine id before each message")
_ = Command.PersistentFlags().Bool(key+".disableTimestamp", false, "allow to disable the timestamp before each message")
_ = Command.PersistentFlags().Bool(key+".enableTrace", true, "allow to add the origin caller/file/line of each message")
_ = Command.PersistentFlags().String(key+".traceFilter", "", "define the path to clean for trace")
_ = Command.PersistentFlags().Bool(key+".disableColor", false, "define if color could be use or not in messages format. If the running process is not a tty, no color will be used.")
if err = vpr.BindPFlag(key+".disableStandard", Command.PersistentFlags().Lookup(key+".disableStandard")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".disableStack", Command.PersistentFlags().Lookup(key+".disableStack")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".disableTimestamp", Command.PersistentFlags().Lookup(key+".disableTimestamp")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".enableTrace", Command.PersistentFlags().Lookup(key+".enableTrace")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".traceFilter", Command.PersistentFlags().Lookup(key+".traceFilter")); err != nil {
return err
} else if err = vpr.BindPFlag(key+".disableColor", Command.PersistentFlags().Lookup(key+".disableColor")); err != nil {
return err
}
return nil
}
func (o *componentLog) _getConfig() (*liblog.Options, liberr.Error) {
var (
key string
cfg liblog.Options
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
if val := vpr.GetBool(key + "disableStandard"); val {
cfg.DisableStandard = true
}
if val := vpr.GetBool(key + "disableStack"); val {
cfg.DisableStack = true
}
if val := vpr.GetBool(key + "disableTimestamp"); val {
cfg.DisableTimestamp = true
}
if val := vpr.GetBool(key + "enableTrace"); val {
cfg.EnableTrace = true
}
if val := vpr.GetString(key + "traceFilter"); val != "" {
cfg.TraceFilter = val
}
if val := vpr.GetBool(key + "disableColor"); val {
cfg.DisableColor = true
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -27,141 +27,9 @@
package log
import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
logdef "github.com/nabbar/golib/logger/config"
)
var _defaultConfig = []byte(`
{
"disableStandard":false,
"disableStack":false,
"disableTimestamp":false,
"enableTrace":true,
"traceFilter":"",
"disableColor":false,
"logFile":[
{
"logLevel":[
"Debug",
"Info",
"Warning",
"Error",
"Fatal",
"Critical"
],
"filepath":"",
"create":false,
"createPath":false,
"fileMode":"0644",
"pathMode":"0755",
"disableStack":false,
"disableTimestamp":false,
"enableTrace":true
}
],
"logSyslog":[
{
"logLevel":[
"Debug",
"Info",
"Warning",
"Error",
"Fatal",
"Critical"
],
"network":"tcp",
"host":"",
"severity":"Error",
"facility":"local0",
"tag":"",
"disableStack":false,
"disableTimestamp":false,
"enableTrace":true
}
]
}`)
func SetDefaultConfig(cfg []byte) {
_defaultConfig = cfg
}
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentLog) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentLog) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
_ = Command.PersistentFlags().Bool(c.key+".disableStandard", false, "allow disabling to write log to standard output stdout/stderr.")
_ = Command.PersistentFlags().Bool(c.key+".disableStack", false, "allow to disable the goroutine id before each message")
_ = Command.PersistentFlags().Bool(c.key+".disableTimestamp", false, "allow to disable the timestamp before each message")
_ = Command.PersistentFlags().Bool(c.key+".enableTrace", true, "allow to add the origin caller/file/line of each message")
_ = Command.PersistentFlags().String(c.key+".traceFilter", "", "define the path to clean for trace")
_ = Command.PersistentFlags().Bool(c.key+".disableColor", false, "define if color could be use or not in messages format. If the running process is not a tty, no color will be used.")
if err := Viper.BindPFlag(c.key+".disableStandard", Command.PersistentFlags().Lookup(c.key+".disableStandard")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".disableStack", Command.PersistentFlags().Lookup(c.key+".disableStack")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".disableTimestamp", Command.PersistentFlags().Lookup(c.key+".disableTimestamp")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".enableTrace", Command.PersistentFlags().Lookup(c.key+".enableTrace")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".traceFilter", Command.PersistentFlags().Lookup(c.key+".traceFilter")); err != nil {
return err
} else if err = Viper.BindPFlag(c.key+".disableColor", Command.PersistentFlags().Lookup(c.key+".disableColor")); err != nil {
return err
}
return nil
}
func (c *componentLog) _GetOptions(getCfg libcfg.FuncComponentConfigGet) (*liblog.Options, liberr.Error) {
var (
err liberr.Error
cfg = liblog.Options{}
vpr = c.vpr()
)
if err = getCfg(c.key, &cfg); err != nil {
return nil, ErrorParamInvalid.Error(err)
}
if val := vpr.GetBool(c.key + "disableStandard"); val {
cfg.DisableStandard = true
}
if val := vpr.GetBool(c.key + "disableStack"); val {
cfg.DisableStack = true
}
if val := vpr.GetBool(c.key + "disableTimestamp"); val {
cfg.DisableTimestamp = true
}
if val := vpr.GetBool(c.key + "enableTrace"); val {
cfg.EnableTrace = true
}
if val := vpr.GetString(c.key + "traceFilter"); val != "" {
cfg.TraceFilter = val
}
if val := vpr.GetBool(c.key + "disableColor"); val {
cfg.DisableColor = true
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
func (o *componentLog) DefaultConfig(indent string) []byte {
return logdef.DefaultConfig(indent)
}

View File

@@ -27,29 +27,38 @@
package log
import (
"sync"
libcfg "github.com/nabbar/golib/config"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
)
const (
DefaultLevel = liblog.InfoLevel
ComponentType = "log"
DefaultLevel = liblog.InfoLevel
)
type ComponentLog interface {
libcfg.Component
cfgtps.Component
Log() liblog.Logger
SetLevel(lvl liblog.Level)
GetLevel() liblog.Level
SetField(fields liblog.Fields)
GetField() liblog.Fields
SetOptions(opt *liblog.Options) liberr.Error
GetOptions() *liblog.Options
}
func New(lvl liblog.Level, defLogger func() liblog.Logger) ComponentLog {
func New(ctx libctx.FuncContext, lvl liblog.Level) ComponentLog {
return &componentLog{
d: defLogger,
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
l: nil,
v: lvl,
}
@@ -59,11 +68,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentLog) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key string, lvl liblog.Level, defLogger func() liblog.Logger) {
cfg.ComponentSet(key, New(lvl, defLogger))
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string, lvl liblog.Level) {
cfg.ComponentSet(key, New(ctx, lvl))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentLog {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentLog {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentLog); !ok {

View File

@@ -29,210 +29,92 @@ package log
import (
"sync"
libcfg "github.com/nabbar/golib/config"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
)
type componentLog struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
m sync.RWMutex
x libctx.Config[uint8]
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
d func() liblog.Logger
m sync.Mutex
l liblog.Logger
v liblog.Level
}
func (c *componentLog) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
func (o *componentLog) Log() liblog.Logger {
o.m.RLock()
defer o.m.RUnlock()
if c.l != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentLog) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
if o.l != nil {
return o.l.Clone()
}
return nil
}
func (c *componentLog) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
func (o *componentLog) SetLevel(lvl liblog.Level) {
o.m.Lock()
defer o.m.Unlock()
if c.ctx == nil {
return ErrorComponentNotInitialized.Error(nil)
}
o.v = lvl
if c.l == nil {
c.l = liblog.New(c.ctx())
c.l.SetLevel(c.v)
}
var (
e error
log liblog.Logger
cnf *liblog.Options
err liberr.Error
)
if log, e = c.l.Clone(); e != nil {
log = liblog.New(c.ctx())
log.SetLevel(c.v)
}
if cnf, err = c._GetOptions(getCfg); err != nil {
return err
} else if cnf == nil {
return ErrorConfigInvalid.Error(nil)
} else if e = log.SetOptions(cnf); e != nil {
return ErrorReloadLog.Error(err)
}
if c.l != nil {
_ = c.l.Close()
}
c.l = log
return nil
}
func (c *componentLog) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentLog) Type() string {
return ComponentType
}
func (c *componentLog) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentLog) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentLog) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentLog) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c.l != nil
}
func (c *componentLog) IsRunning(atLeast bool) bool {
return c.IsStarted()
}
func (c *componentLog) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentLog) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentLog) Stop() {
return
}
func (c *componentLog) Dependencies() []string {
return make([]string, 0)
}
func (c *componentLog) Log() liblog.Logger {
c.m.Lock()
defer c.m.Unlock()
if c.l != nil {
if n, e := c.l.Clone(); e != nil {
return c.d()
} else {
return n
}
}
return c.d()
}
func (c *componentLog) SetLevel(lvl liblog.Level) {
c.m.Lock()
defer c.m.Unlock()
c.v = lvl
if c.l == nil {
if o.l == nil {
return
}
c.l.SetLevel(lvl)
o.l.SetLevel(lvl)
}
func (c *componentLog) SetField(fields liblog.Fields) {
c.m.Lock()
defer c.m.Unlock()
func (o *componentLog) GetLevel() liblog.Level {
o.m.RLock()
defer o.m.RUnlock()
if c.l == nil {
return o.v
}
func (o *componentLog) SetField(fields liblog.Fields) {
o.m.Lock()
defer o.m.Unlock()
if o.l == nil {
return
}
c.l.SetFields(fields)
o.l.SetFields(fields)
}
func (c *componentLog) SetOptions(opt *liblog.Options) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
func (o *componentLog) GetField() liblog.Fields {
o.m.RLock()
defer o.m.RUnlock()
if c.l == nil {
if o.l == nil {
return nil
}
return o.l.GetFields()
}
func (o *componentLog) GetOptions() *liblog.Options {
o.m.RLock()
defer o.m.RUnlock()
if o.l == nil {
return nil
}
return o.l.GetOptions()
}
func (o *componentLog) SetOptions(opt *liblog.Options) liberr.Error {
o.m.Lock()
defer o.m.Unlock()
if o.l == nil {
return ErrorComponentNotInitialized.Error(nil)
}
if e := c.l.SetOptions(opt); e != nil {
if e := o.l.SetOptions(opt); e != nil {
return ErrorConfigInvalid.ErrorParent(e)
}

View File

@@ -0,0 +1,34 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package log
import (
montps "github.com/nabbar/golib/monitor/types"
)
func (o *componentLog) RegisterMonitorPool(fct montps.FuncPool) {
}

View File

@@ -0,0 +1,197 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package mail
import (
"context"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
libmail "github.com/nabbar/golib/mail"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentMail) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentMail) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentMail) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentMail) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentMail) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentMail) _getContext() context.Context {
o.m.RLock()
defer o.m.RUnlock()
return o.x.GetContext()
}
func (o *componentMail) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentMail) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentMail) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentMail) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentMail) _runCli() liberr.Error {
var (
err liberr.Error
prt = ErrorComponentReload
obj libmail.Mail
cfg *libmail.Config
)
if !o.IsStarted() {
prt = ErrorComponentStart
}
if cfg, err = o._getConfig(); err != nil {
return prt.Error(err)
} else if obj, err = cfg.NewMailer(); err != nil {
return prt.Error(err)
}
o.Stop()
o.m.Lock()
o.e = obj
o.m.Unlock()
return nil
}
func (o *componentMail) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,155 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package mail
import (
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "smtp"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentMail) Type() string {
return ComponentType
}
func (o *componentMail) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentMail) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentMail) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentMail) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o != nil && o.e != nil
}
func (o *componentMail) IsRunning() bool {
return o.IsStarted()
}
func (o *componentMail) Start() liberr.Error {
return o._run()
}
func (o *componentMail) Reload() liberr.Error {
return o._run()
}
func (o *componentMail) Stop() {
o.m.Lock()
defer o.m.Unlock()
o.e = nil
return
}
func (o *componentMail) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = make([]string, 0)
if o == nil {
return def
} else if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentMail) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentMail) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,150 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package mail
import (
liberr "github.com/nabbar/golib/errors"
libmail "github.com/nabbar/golib/mail"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentMail) RegisterFlag(Command *spfcbr.Command) error {
var (
key string
vpr *spfvpr.Viper
)
if vpr = o._getSPFViper(); vpr == nil {
return ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
}
_ = Command.PersistentFlags().String(key+".charset", "", "define the charset to use into mail header")
_ = Command.PersistentFlags().String(key+".encoding", "", "define the encoding mode for contents of mail")
_ = Command.PersistentFlags().String(key+".priority", "", "define the priority of the mail")
_ = Command.PersistentFlags().String(key+".subject", "", "define the subject of the mail")
_ = Command.PersistentFlags().String(key+".from", "", "define the email use for sending the mail")
_ = Command.PersistentFlags().String(key+".sender", "", "define the email show as sender")
_ = Command.PersistentFlags().String(key+".replyTo", "", "define the email to use for reply")
if err := vpr.BindPFlag(key+".charset", Command.PersistentFlags().Lookup(key+".charset")); err != nil {
return err
}
if err := vpr.BindPFlag(key+".encoding", Command.PersistentFlags().Lookup(key+".encoding")); err != nil {
return err
}
if err := vpr.BindPFlag(key+".priority", Command.PersistentFlags().Lookup(key+".priority")); err != nil {
return err
}
if err := vpr.BindPFlag(key+".subject", Command.PersistentFlags().Lookup(key+".subject")); err != nil {
return err
}
if err := vpr.BindPFlag(key+".from", Command.PersistentFlags().Lookup(key+".from")); err != nil {
return err
}
if err := vpr.BindPFlag(key+".sender", Command.PersistentFlags().Lookup(key+".sender")); err != nil {
return err
}
if err := vpr.BindPFlag(key+".replyTo", Command.PersistentFlags().Lookup(key+".replyTo")); err != nil {
return err
}
return nil
}
func (o *componentMail) _getConfig() (*libmail.Config, liberr.Error) {
var (
key string
cfg libmail.Config
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
if len(cfg.Headers) < 1 {
cfg.Headers = make(map[string]string, 0)
}
if len(cfg.To) < 1 {
cfg.To = make([]string, 0)
}
if len(cfg.Cc) < 1 {
cfg.Cc = make([]string, 0)
}
if len(cfg.Bcc) < 1 {
cfg.Bcc = make([]string, 0)
}
if len(cfg.Attach) < 1 {
cfg.Attach = make([]libmail.ConfigFile, 0)
}
if len(cfg.Inline) < 1 {
cfg.Inline = make([]libmail.ConfigFile, 0)
}
if val := vpr.GetString(key + ".charset"); val != "" {
cfg.Charset = val
}
if val := vpr.GetString(key + ".encoding"); val != "" {
cfg.Encoding = val
}
if val := vpr.GetString(key + ".priority"); val != "" {
cfg.Priority = val
}
if val := vpr.GetString(key + ".subject"); val != "" {
cfg.Subject = val
}
if val := vpr.GetString(key + ".from"); val != "" {
cfg.From = val
}
if val := vpr.GetString(key + ".sender"); val != "" {
cfg.Sender = val
}
if val := vpr.GetString(key + ".replyTo"); val != "" {
cfg.ReplyTo = val
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -30,11 +30,7 @@ import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
libmail "github.com/nabbar/golib/mail"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgtps "github.com/nabbar/golib/config/const"
)
var _defaultConfig = []byte(`{
@@ -80,111 +76,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgtps.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentMail) DefaultConfig(indent string) []byte {
func (o *componentMail) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentMail) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
_ = Command.PersistentFlags().String(c.key+".charset", "", "define the charset to use into mail header")
_ = Command.PersistentFlags().String(c.key+".encoding", "", "define the encoding mode for contents of mail")
_ = Command.PersistentFlags().String(c.key+".priority", "", "define the priority of the mail")
_ = Command.PersistentFlags().String(c.key+".subject", "", "define the subject of the mail")
_ = Command.PersistentFlags().String(c.key+".from", "", "define the email use for sending the mail")
_ = Command.PersistentFlags().String(c.key+".sender", "", "define the email show as sender")
_ = Command.PersistentFlags().String(c.key+".replyTo", "", "define the email to use for reply")
if err := Viper.BindPFlag(c.key+".charset", Command.PersistentFlags().Lookup(c.key+".charset")); err != nil {
return err
}
if err := Viper.BindPFlag(c.key+".encoding", Command.PersistentFlags().Lookup(c.key+".encoding")); err != nil {
return err
}
if err := Viper.BindPFlag(c.key+".priority", Command.PersistentFlags().Lookup(c.key+".priority")); err != nil {
return err
}
if err := Viper.BindPFlag(c.key+".subject", Command.PersistentFlags().Lookup(c.key+".subject")); err != nil {
return err
}
if err := Viper.BindPFlag(c.key+".from", Command.PersistentFlags().Lookup(c.key+".from")); err != nil {
return err
}
if err := Viper.BindPFlag(c.key+".sender", Command.PersistentFlags().Lookup(c.key+".sender")); err != nil {
return err
}
if err := Viper.BindPFlag(c.key+".replyTo", Command.PersistentFlags().Lookup(c.key+".replyTo")); err != nil {
return err
}
return nil
}
func (c *componentMail) _getConfig(getCfg libcfg.FuncComponentConfigGet) (libmail.Config, liberr.Error) {
var (
cfg = libmail.Config{}
vpr = c.vpr()
err liberr.Error
)
if len(cfg.Headers) < 1 {
cfg.Headers = make(map[string]string, 0)
}
if len(cfg.To) < 1 {
cfg.To = make([]string, 0)
}
if len(cfg.Cc) < 1 {
cfg.Cc = make([]string, 0)
}
if len(cfg.Bcc) < 1 {
cfg.Bcc = make([]string, 0)
}
if len(cfg.Attach) < 1 {
cfg.Attach = make([]libmail.ConfigFile, 0)
}
if len(cfg.Inline) < 1 {
cfg.Inline = make([]libmail.ConfigFile, 0)
}
if e := getCfg(c.key, &cfg); e != nil {
return cfg, ErrorParamInvalid.Error(e)
}
if val := vpr.GetString(c.key + ".charset"); val != "" {
cfg.Charset = val
}
if val := vpr.GetString(c.key + ".encoding"); val != "" {
cfg.Encoding = val
}
if val := vpr.GetString(c.key + ".priority"); val != "" {
cfg.Priority = val
}
if val := vpr.GetString(c.key + ".subject"); val != "" {
cfg.Subject = val
}
if val := vpr.GetString(c.key + ".from"); val != "" {
cfg.From = val
}
if val := vpr.GetString(c.key + ".sender"); val != "" {
cfg.Sender = val
}
if val := vpr.GetString(c.key + ".replyTo"); val != "" {
cfg.ReplyTo = val
}
if err = cfg.Validate(); err != nil {
return cfg, ErrorConfigInvalid.Error(err)
}
return cfg, nil
}

View File

@@ -38,10 +38,8 @@ const (
ErrorParamInvalid
ErrorComponentNotInitialized
ErrorConfigInvalid
ErrorStartComponent
ErrorReloadComponent
ErrorDependencyTLSDefault
ErrorDependencyLogDefault
ErrorComponentStart
ErrorComponentReload
)
func init() {
@@ -61,14 +59,10 @@ func getMessage(code liberr.CodeError) (message string) {
return "this component seems to not be correctly initialized"
case ErrorConfigInvalid:
return "invalid component config"
case ErrorStartComponent:
case ErrorComponentStart:
return "cannot start component with config"
case ErrorReloadComponent:
case ErrorComponentReload:
return "cannot reload component with new config"
case ErrorDependencyTLSDefault:
return "cannot retrieve TLS Component"
case ErrorDependencyLogDefault:
return "cannot retrieve Logger Component"
}
return liberr.NullMessage

View File

@@ -30,30 +30,23 @@ import (
"sync"
libcfg "github.com/nabbar/golib/config"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
libmail "github.com/nabbar/golib/mail"
)
const (
ComponentType = "smtp"
)
type ComponentMail interface {
libcfg.Component
cfgtps.Component
GetMail() (libmail.Mail, liberr.Error)
}
func New() ComponentMail {
func New(ctx libctx.FuncContext) ComponentMail {
return &componentMail{
ctx: nil,
get: nil,
fsa: nil,
fsb: nil,
fra: nil,
frb: nil,
m: sync.Mutex{},
e: nil,
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
e: nil,
}
}
@@ -61,11 +54,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentMail) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New())
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New(ctx))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentMail {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentMail {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentMail); !ok {

View File

@@ -29,155 +29,24 @@ package mail
import (
"sync"
libcfg "github.com/nabbar/golib/config"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
libmail "github.com/nabbar/golib/mail"
)
type componentMail struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
m sync.RWMutex
x libctx.Config[uint8]
e libmail.Mail
}
func (c *componentMail) _CheckDep() bool {
return c != nil
}
func (c *componentMail) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
if c.e != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentMail) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentMail) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
var (
err liberr.Error
mlr libmail.Mail
cfg libmail.Config
)
if cfg, err = c._getConfig(getCfg); err != nil {
return err
} else if mlr, err = cfg.NewMailer(); err != nil {
return err
} else {
c.e = mlr
}
return nil
}
func (c *componentMail) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
if !c._CheckDep() {
return ErrorComponentNotInitialized.Error(nil)
}
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentMail) Type() string {
return ComponentType
}
func (c *componentMail) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentMail) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentMail) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentMail) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c._CheckDep() && c.e != nil
}
func (c *componentMail) IsRunning(atLeast bool) bool {
return !c.IsStarted()
}
func (c *componentMail) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentMail) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentMail) Stop() {
c.m.Lock()
defer c.m.Unlock()
c.e = nil
}
func (c *componentMail) Dependencies() []string {
return make([]string, 0)
}
func (c *componentMail) GetMail() (libmail.Mail, liberr.Error) {
if !c.IsStarted() {
func (o *componentMail) GetMail() (libmail.Mail, liberr.Error) {
if !o.IsStarted() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
c.m.Lock()
defer c.m.Unlock()
o.m.Lock()
defer o.m.Unlock()
return c.e.Clone(), nil
return o.e.Clone(), nil
}

View File

@@ -0,0 +1,34 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package mail
import (
montps "github.com/nabbar/golib/monitor/types"
)
func (o *componentMail) RegisterMonitorPool(fct montps.FuncPool) {
}

View File

@@ -1,316 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package natsServer
import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
cpttls "github.com/nabbar/golib/config/components/tls"
liberr "github.com/nabbar/golib/errors"
libnat "github.com/nabbar/golib/nats"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
)
var _defaultConfig = []byte(`{
"server":{
"name":"node-0",
"host":"127.0.0.1",
"port":9000,
"client_advertise":"",
"http_host":"127.0.0.1",
"http_port":9200,
"https_port":0,
"http_base_path":"",
"prof_port":9300,
"pid_file":"",
"ports_file_dir":"",
"routes":[
{
"Scheme":"nats",
"Opaque":"",
"User":{
},
"Host":"127.0.0.1:9101",
"Path":"",
"RawPath":"",
"ForceQuery":false,
"RawQuery":"",
"Fragment":"",
"RawFragment":""
},
{
"Scheme":"nats",
"Opaque":"",
"User":{
},
"Host":"127.0.0.1:9102",
"Path":"",
"RawPath":"",
"ForceQuery":false,
"RawQuery":"",
"Fragment":"",
"RawFragment":""
},
{
"Scheme":"nats",
"Opaque":"",
"User":{
},
"Host":"127.0.0.1:9103",
"Path":"",
"RawPath":"",
"ForceQuery":false,
"RawQuery":"",
"Fragment":"",
"RawFragment":""
}
],
"routes_str":"nats://127.0.0.1:9101,nats://127.0.0.1:9102,nats://127.0.0.1:9103",
"no_log":true,
"username":"",
"password":"",
"token":"",
"jet_stream":true,
"jet_stream_max_memory":0,
"jet_stream_max_store":0,
"store_dir":"/path/to/working/folder",
"permission_store_dir":"0755",
"tags":[
""
],
"tls":false,
"allow_no_tls":true,
"tls_timeout":0,
"tls_config":` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
},
"cluster":{
"name":"Test-cluster",
"host":"127.0.0.1",
"port":9100,
"listen_str":"",
"advertise":"",
"no_advertise":false,
"connect_retries":5,
"username":"",
"password":"",
"auth_timeout":0,
"permissions":{
"import":{
"allow":null,
"deny":null
},
"export":{
"allow":null,
"deny":null
}
},
"tls":false,
"tls_timeout":0,
"tls_config":` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
},
"gateways":{
"name":"",
"host":"",
"port":0,
"username":"",
"password":"",
"auth_timeout":0,
"advertise":"",
"connect_retries":0,
"gateways":null,
"reject_unknown":false,
"tls":false,
"tls_timeout":0,
"tls_config":` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
},
"leaf":{
"host":"",
"port":0,
"username":"",
"password":"",
"auth_timeout":0,
"advertise":"",
"no_advertise":false,
"account":"",
"users":null,
"reconnect_interval":0,
"remotes":null,
"tls":false,
"tls_timeout":0,
"tls_config":` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
},
"websockets":{
"host":"",
"port":0,
"advertise":"",
"no_auth_user":"",
"jwt_cookie":"",
"username":"",
"password":"",
"token":"",
"auth_timeout":0,
"same_origin":false,
"allowed_origins":null,
"compression":false,
"no_tls":false,
"handshake_timeout":0,
"tls_config":` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
},
"mqtt":{
"host":"",
"port":0,
"no_auth_user":"",
"username":"",
"password":"",
"token":"",
"auth_timeout":0,
"ack_wait":0,
"max_ack_pending":0,
"tls":false,
"tls_timeout":0,
"tls_config": ` + string(cpttls.DefaultConfig(libcfg.JSONIndent+libcfg.JSONIndent)) + `
},
"limits":{
"max_conn":0,
"max_subs":0,
"ping_interval":0,
"max_pings_out":0,
"max_control_line":0,
"max_payload":0,
"max_pending":0,
"write_deadline":0,
"max_closed_clients":0,
"lame_duck_duration":0,
"lame_duck_grace_period":0,
"no_sublist_cache":false,
"no_header_support":false,
"disable_short_first_ping":false
},
"logs":{
"log_file":"/path/to/log/file.log",
"permission_folder":"0755",
"permission_file":"0644",
"syslog":false,
"remote_syslog":"",
"log_size_limit":0,
"max_traced_msg_len":0,
"connect_error_reports":0,
"reconnect_error_reports":0
},
"auth":{
"nkeys":null,
"users":[
{
"username":"username",
"password":"password",
"account":"cluster",
"connection_types":[
"STANDARD",
"LEAFNODE",
"WEBSOCKET",
"MQTT"
]
}
],
"accounts":[
{
"name":"cluster",
"permission":{
"publish":{
"allow":[
">",
"*"
],
"deny":[]
},
"subscribe":{
"allow":[
">",
"*"
],
"deny":[]
},
"response":{
"max_msgs":1000000000,
"expires":1
}
}
}
],
"auth_timeout":0,
"no_auth_user":"",
"system_account":"cluster",
"no_system_account":false,
"allow_new_accounts":true,
"trusted_keys":[],
"trusted_operators":[]
}
}`)
func SetDefaultConfig(cfg []byte) {
_defaultConfig = cfg
}
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentNats) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentNats) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
return nil
}
func (c *componentNats) _getConfig(getCfg libcfg.FuncComponentConfigGet) (libnat.Config, liberr.Error) {
var (
cfg = libnat.Config{}
err liberr.Error
)
if e := getCfg(c.key, &cfg); e != nil {
return cfg, ErrorParamInvalid.Error(e)
}
if err = cfg.Validate(); err != nil {
return cfg, ErrorConfigInvalid.Error(err)
}
return cfg, nil
}

View File

@@ -1,249 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package natsServer
import (
"sync"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
cpttls "github.com/nabbar/golib/config/components/tls"
liberr "github.com/nabbar/golib/errors"
libnat "github.com/nabbar/golib/nats"
libsts "github.com/nabbar/golib/status"
natsrv "github.com/nats-io/nats-server/v2/server"
)
type componentNats struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
t string
n libnat.Server
}
func (c *componentNats) _CheckDep() bool {
return c != nil && c.t != ""
}
func (c *componentNats) _GetTLS() (libtls.TLSConfig, liberr.Error) {
if !c._CheckDep() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if i := cpttls.Load(c.get, c.t); i == nil {
return nil, ErrorDependencyTLSDefault.Error(nil)
} else if tls := i.GetTLS(); tls == nil {
return nil, ErrorDependencyTLSDefault.Error(nil)
} else {
return tls, nil
}
}
func (c *componentNats) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
if c.n != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentNats) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentNats) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
var (
tls libtls.TLSConfig
err liberr.Error
cfg libnat.Config
opt *natsrv.Options
)
if cfg, err = c._getConfig(getCfg); err != nil {
return err
}
if tls, err = c._GetTLS(); err != nil {
return err
}
if opt, err = cfg.NatsOption(tls); err != nil {
return ErrorStartComponent.Error(err)
}
if c.n != nil {
c.n.SetOptions(opt)
if err = c.n.Restart(c.ctx()); err != nil {
return ErrorReloadComponent.Error(err)
}
} else {
c.n = libnat.NewServer(opt, cfg.Status)
if err = c.n.Listen(c.ctx()); err != nil {
return err
}
}
return nil
}
func (c *componentNats) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
if !c._CheckDep() {
return ErrorComponentNotInitialized.Error(nil)
}
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentNats) Type() string {
return ComponentType
}
func (c *componentNats) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentNats) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentNats) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentNats) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c != nil && c.n != nil
}
func (c *componentNats) IsRunning(atLeast bool) bool {
if c.IsStarted() {
c.m.Lock()
defer c.m.Unlock()
return c.n.IsRunning()
}
return false
}
func (c *componentNats) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentNats) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentNats) Stop() {
if c.IsRunning(true) {
c.m.Lock()
defer c.m.Unlock()
c.n.Shutdown()
}
}
func (c *componentNats) Dependencies() []string {
c.m.Lock()
defer c.m.Unlock()
if !c._CheckDep() {
return []string{cpttls.ComponentType}
}
return []string{c.t}
}
func (c *componentNats) SetTLSKey(tlsKey string) {
c.m.Lock()
defer c.m.Unlock()
c.t = tlsKey
}
func (c *componentNats) GetServer() (libnat.Server, liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
if c == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
}
return c.n, nil
}
func (c *componentNats) SetStatusRouter(sts libsts.RouteStatus, prefix string) {
c.m.Lock()
defer c.m.Unlock()
c.n.StatusRouter(sts, prefix)
}

View File

@@ -1,153 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package nutsdb
import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
libndb "github.com/nabbar/golib/nutsdb"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
)
var _defaultConfig = []byte(`{
"db":{
"entry_idx_mode":0,
"rw_mode":0,
"segment_size":8388608,
"sync_enable":false,
"start_file_loading_mode":1
},
"cluster":{
"node":{
"deployment_id":0,
"wal_dir":"",
"node_host_dir":"",
"rtt_millisecond":200,
"raft_address":"localhost:9001",
"address_by_node_host_id":false,
"listen_address":"",
"mutual_tls":false,
"ca_file":"",
"cert_file":"",
"key_file":"",
"enable_metrics":true,
"max_send_queue_size":0,
"max_receive_queue_size":0,
"max_snapshot_send_bytes_per_second":0,
"max_snapshot_recv_bytes_per_second":0,
"notify_commit":false,
"gossip":{
"bind_address":"",
"advertise_address":"",
"seed":null
},
"expert":{
"engine":{
"exec_shards":0,
"commit_shards":0,
"apply_shards":0,
"snapshot_shards":0,
"close_shards":0
},
"test_node_host_id":0,
"test_gossip_probe_interval":0
}
},
"cluster":{
"node_id":1,
"cluster_id":1,
"check_quorum":true,
"election_rtt":15,
"heartbeat_rtt":1,
"snapshot_entries":10,
"compaction_overhead":0,
"ordered_config_change":false,
"max_in_mem_log_size":0,
"snapshot_compression":0,
"entry_compression":0,
"disable_auto_compactions":true,
"is_observer":false,
"is_witness":false,
"quiesce":false
},
"init_member":{
"1":"localhost:9001"
}
},
"directories":{
"base":"/tmp/nutsdb/node-%d",
"sub_data":"data",
"sub_backup":"backup",
"sub_temp":"temp",
"wal_dir":"",
"host_dir":"",
"limit_number_backup":5,
"permission":504
}
}`)
func SetDefaultConfig(cfg []byte) {
_defaultConfig = cfg
}
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentNutsDB) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentNutsDB) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
return nil
}
func (c *componentNutsDB) _getConfig(getCfg libcfg.FuncComponentConfigGet) (libndb.Config, liberr.Error) {
var (
cfg = libndb.Config{}
err liberr.Error
)
if e := getCfg(c.key, &cfg); e != nil {
return cfg, ErrorParamInvalid.Error(e)
}
if err = cfg.Validate(); err != nil {
return cfg, ErrorConfigInvalid.Error(err)
}
return cfg, nil
}

View File

@@ -1,262 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package nutsdb
import (
"sync"
"time"
libcfg "github.com/nabbar/golib/config"
cptlog "github.com/nabbar/golib/config/components/log"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libndb "github.com/nabbar/golib/nutsdb"
libsts "github.com/nabbar/golib/status"
)
type componentNutsDB struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
l string
n libndb.NutsDB
}
func (c *componentNutsDB) _CheckDep() bool {
return c != nil && c.l != ""
}
func (c *componentNutsDB) _GetLogger() (liblog.Logger, liberr.Error) {
if !c._CheckDep() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if i := cptlog.Load(c.get, c.l); i == nil {
return nil, ErrorDependencyLogDefault.Error(nil)
} else if log := i.Log(); log == nil {
return nil, ErrorDependencyLogDefault.Error(nil)
} else {
return log, nil
}
}
func (c *componentNutsDB) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
if c.n != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentNutsDB) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentNutsDB) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
var (
err liberr.Error
cfg libndb.Config
)
if cfg, err = c._getConfig(getCfg); err != nil {
return err
}
srv := libndb.New(cfg)
srv.SetLogger(func() liblog.Logger {
var (
l liblog.Logger
e liberr.Error
)
if l, e = c._GetLogger(); e != nil {
return liblog.GetDefault()
} else {
return l
}
})
if err = srv.Listen(); err != nil {
return err
}
if c.n != nil {
_ = c.n.Shutdown()
}
c.n = srv
return nil
}
func (c *componentNutsDB) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
if !c._CheckDep() {
return ErrorComponentNotInitialized.Error(nil)
}
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentNutsDB) Type() string {
return ComponentType
}
func (c *componentNutsDB) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentNutsDB) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentNutsDB) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentNutsDB) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c._CheckDep() && c.n != nil
}
func (c *componentNutsDB) IsRunning(atLeast bool) bool {
if c.IsStarted() {
c.m.Lock()
defer c.m.Unlock()
return c.n.IsRunning()
}
return false
}
func (c *componentNutsDB) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentNutsDB) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentNutsDB) Stop() {
if c.IsRunning(true) {
c.m.Lock()
defer c.m.Unlock()
_ = c.n.Shutdown()
}
}
func (c *componentNutsDB) Dependencies() []string {
c.m.Lock()
defer c.m.Unlock()
if !c._CheckDep() {
return []string{cptlog.ComponentType}
}
return []string{c.l}
}
func (c *componentNutsDB) GetServer() (libndb.NutsDB, liberr.Error) {
if c.IsStarted() {
c.m.Lock()
defer c.m.Unlock()
return c.n, nil
}
return nil, ErrorComponentNotInitialized.Error(nil)
}
func (c *componentNutsDB) SetLogger(key string) {
c.m.Lock()
defer c.m.Unlock()
c.l = key
}
func (c *componentNutsDB) GetClient(tickSync time.Duration) (libndb.Client, liberr.Error) {
if c != nil && c.IsStarted() {
c.m.Lock()
defer c.m.Unlock()
return c.n.Client(c.ctx(), tickSync), nil
}
return nil, ErrorComponentNotInitialized.Error(nil)
}
func (c *componentNutsDB) SetStatusRouter(sts libsts.RouteStatus, prefix string) {
c.m.Lock()
defer c.m.Unlock()
c.n.StatusRouter(sts, prefix)
}

Binary file not shown.

View File

@@ -0,0 +1,233 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package request
import (
"context"
libtls "github.com/nabbar/golib/certificates"
cpttls "github.com/nabbar/golib/config/components/tls"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
libreq "github.com/nabbar/golib/request"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentRequest) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentRequest) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentRequest) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentRequest) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentRequest) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentRequest) _getContext() context.Context {
o.m.RLock()
defer o.m.RUnlock()
return o.x.GetContext()
}
func (o *componentRequest) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentRequest) _GetTLS() libtls.TLSConfig {
o.m.RLock()
defer o.m.RUnlock()
if o.t == "" {
return nil
}
if i := cpttls.Load(o._getFctCpt(), o.t); i == nil {
return nil
} else if tls := i.GetTLS(); tls == nil {
return nil
} else {
return tls
}
}
func (o *componentRequest) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentRequest) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentRequest) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentRequest) _runCli() liberr.Error {
var (
e error
err liberr.Error
prt = ErrorComponentReload
req libreq.Request
cfg *libreq.Options
)
if !o.IsStarted() {
prt = ErrorComponentStart
} else {
req = o.r
}
if cfg, err = o._getConfig(); err != nil {
return prt.Error(err)
}
cfg.SetDefaultTLS(o._GetTLS)
cfg.SetDefaultLog(o.getLogger)
if req != nil {
req.RegisterDefaultLogger(o.getLogger)
if req, e = cfg.Update(o.x.GetContext, req); err != nil {
return prt.ErrorParent(e)
}
} else {
if req, e = cfg.New(o.x.GetContext); err != nil {
return prt.ErrorParent(e)
}
}
o.m.Lock()
o.r = req
o.m.Unlock()
if e = o._registerMonitor(cfg); e != nil {
return prt.ErrorParent(e)
}
return nil
}
func (o *componentRequest) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,160 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package request
import (
cpttls "github.com/nabbar/golib/config/components/tls"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "request"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentRequest) Type() string {
return ComponentType
}
func (o *componentRequest) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentRequest) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentRequest) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentRequest) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o != nil && o.r != nil
}
func (o *componentRequest) IsRunning() bool {
return o.IsStarted()
}
func (o *componentRequest) Start() liberr.Error {
return o._run()
}
func (o *componentRequest) Reload() liberr.Error {
return o._run()
}
func (o *componentRequest) Stop() {
o.m.Lock()
defer o.m.Unlock()
o.r = nil
return
}
func (o *componentRequest) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = []string{cpttls.ComponentType}
if o == nil {
return def
} else if len(o.t) > 0 {
def = []string{o.t}
}
if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentRequest) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentRequest) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,63 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package request
import (
liberr "github.com/nabbar/golib/errors"
libreq "github.com/nabbar/golib/request"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentRequest) RegisterFlag(Command *spfcbr.Command) error {
return nil
}
func (o *componentRequest) _getConfig() (*libreq.Options, liberr.Error) {
var (
key string
cfg libreq.Options
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -30,25 +30,14 @@ import (
"bytes"
"encoding/json"
libcfg "github.com/nabbar/golib/config"
cmptls "github.com/nabbar/golib/config/components/tls"
libsts "github.com/nabbar/golib/status/config"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgcst "github.com/nabbar/golib/config/const"
libhtc "github.com/nabbar/golib/httpcli"
moncfg "github.com/nabbar/golib/monitor/types"
)
var _defaultConfig = []byte(`{
"endpoint":"https://endpoint.example.com/path",
"http_client": {
"timeout":"0s",
"http2": true,
"tls": ` + string(cmptls.DefaultConfig(" ")) + `,
"force_ip": {
"enable": false,
"net":"tcp",
"ip":"127.0.0.1:8080"
}
},
"http_client": ` + string(libhtc.DefaultConfig(cfgcst.JSONIndent)) + `,
"auth": {
"basic":{
"enable": false,
@@ -80,7 +69,7 @@ var _defaultConfig = []byte(`{
"contain": ["OK", "Done"],
"not_contain": ["KO", "fail", "error"]
},
"status": ` + string(libsts.DefaultConfig(" ")) + `
"monitor": ` + string(moncfg.DefaultConfig(cfgcst.JSONIndent)) + `
}
}`)
@@ -90,17 +79,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentRequest) DefaultConfig(indent string) []byte {
func (o *componentRequest) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentRequest) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
return nil
}

View File

@@ -39,6 +39,8 @@ const (
ErrorComponentNotInitialized
ErrorConfigInvalid
ErrorDependencyTLSDefault
ErrorComponentStart
ErrorComponentReload
)
func init() {
@@ -60,6 +62,10 @@ func getMessage(code liberr.CodeError) (message string) {
return "server invalid config"
case ErrorDependencyTLSDefault:
return "cannot retrieve TLS component"
case ErrorComponentStart:
return "cannot start component with config"
case ErrorComponentReload:
return "cannot restart component with new config"
}
return liberr.NullMessage

View File

@@ -30,28 +30,24 @@ import (
"sync"
libcfg "github.com/nabbar/golib/config"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
libreq "github.com/nabbar/golib/request"
)
const (
ComponentType = "request"
)
type ComponentRequest interface {
libcfg.Component
cfgtps.Component
SetHTTPClient(fct libreq.FctHttpClient)
SetDefaultTLS(key string)
Request() (libreq.Request, error)
}
func New(tls string, cli libreq.FctHttpClient) ComponentRequest {
func New(ctx libctx.FuncContext, tls string) ComponentRequest {
return &componentRequest{
m: sync.Mutex{},
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
r: nil,
t: tls,
c: cli,
}
}
@@ -59,11 +55,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentRequest) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key, tls string, cli libreq.FctHttpClient) {
cfg.ComponentSet(key, New(tls, cli))
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key, tls string) {
cfg.ComponentSet(key, New(ctx, tls))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentRequest {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentRequest {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentRequest); !ok {

View File

@@ -27,214 +27,31 @@
package request
import (
"context"
"sync"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
cpttls "github.com/nabbar/golib/config/components/tls"
liberr "github.com/nabbar/golib/errors"
libctx "github.com/nabbar/golib/context"
montps "github.com/nabbar/golib/monitor/types"
libreq "github.com/nabbar/golib/request"
)
type componentRequest struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
sts libcfg.FuncRouteStatus
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
m sync.RWMutex
x libctx.Config[uint8]
r libreq.Request
t string
c libreq.FctHttpClient
p montps.FuncPool
}
func (c *componentRequest) _GetContext() context.Context {
c.m.Lock()
defer c.m.Unlock()
func (o *componentRequest) SetDefaultTLS(key string) {
o.m.Lock()
defer o.m.Unlock()
if c.ctx != nil {
if x := c.ctx(); x != nil {
return x
}
}
return context.Background()
o.t = key
}
func (c *componentRequest) _CheckInit() bool {
return c != nil && c.r != nil
}
func (c *componentRequest) _GetTLS() libtls.TLSConfig {
if c.t == "" {
return nil
}
if i := cpttls.Load(c.get, c.t); i == nil {
return nil
} else if tls := i.GetTLS(); tls == nil {
return nil
} else {
return tls
}
}
func (c *componentRequest) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
if c.r != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentRequest) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentRequest) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
cfg := libreq.Options{}
cfg.SetDefaultTLS(c._GetTLS)
if err := getCfg(c.key, &cfg); err != nil {
return ErrorParamInvalid.Error(err)
}
if c.r == nil {
if r, e := cfg.New(c._GetContext, c.c, c._GetTLS); e != nil {
return ErrorConfigInvalid.ErrorParent(e)
} else {
c.r = r
}
} else {
if r, e := cfg.Update(c.r, c._GetContext, c.c, c._GetTLS); e != nil {
return ErrorConfigInvalid.ErrorParent(e)
} else {
c.r = r
}
}
if c.sts != nil {
if s := c.sts(); s != nil {
c.r.StatusRegister(s, c.key)
}
}
return nil
}
func (c *componentRequest) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentRequest) Type() string {
return ComponentType
}
func (c *componentRequest) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
c.sts = sts
}
func (c *componentRequest) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentRequest) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentRequest) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c != nil && c.r != nil
}
func (c *componentRequest) IsRunning(atLeast bool) bool {
return c.IsStarted()
}
func (c *componentRequest) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentRequest) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentRequest) Stop() {
}
func (c *componentRequest) Dependencies() []string {
c.m.Lock()
defer c.m.Unlock()
if c == nil || c.t == "" {
return []string{cpttls.ComponentType}
}
return []string{c.t}
}
func (c *componentRequest) SetHTTPClient(fct libreq.FctHttpClient) {
c.m.Lock()
defer c.m.Unlock()
c.c = fct
}
func (c *componentRequest) SetDefaultTLS(key string) {
c.m.Lock()
defer c.m.Unlock()
c.t = key
}
func (c *componentRequest) Request() (libreq.Request, error) {
c.m.Lock()
defer c.m.Unlock()
return c.r.Clone()
func (o *componentRequest) Request() (libreq.Request, error) {
o.m.RLock()
defer o.m.RUnlock()
return o.r.Clone()
}

View File

@@ -0,0 +1,133 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package request
import (
"context"
montps "github.com/nabbar/golib/monitor/types"
libreq "github.com/nabbar/golib/request"
libver "github.com/nabbar/golib/version"
)
func (o *componentRequest) RegisterMonitorPool(fct montps.FuncPool) {
o.m.Lock()
defer o.m.Unlock()
o.p = fct
}
func (o *componentRequest) _getMonitorPool() montps.Pool {
o.m.RLock()
defer o.m.RUnlock()
if o.p == nil {
return nil
} else if p := o.p(); p == nil {
return nil
} else {
return p
}
}
func (o *componentRequest) _registerMonitor(cfg *libreq.Options) error {
var (
e error
key = o._getKey()
mon montps.Monitor
vrs = o._getVersion()
ctx = o._getContext()
)
if o._getMonitorPool() == nil {
return nil
} else if len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
} else if cfg == nil {
return ErrorConfigInvalid.Error(nil)
} else if !o.IsStarted() {
return ErrorComponentStart.Error(nil)
} else if ctx == nil {
ctx = context.Background()
}
if mon, e = o._newMonitor(ctx, vrs); e != nil {
return e
}
if m := o._getMonitor(mon.Name()); m != nil {
mon = m
}
if mon == nil {
return nil
}
mon.RegisterLoggerDefault(o.getLogger)
if e = mon.SetConfig(o.x.GetContext, cfg.Health.Monitor); e != nil {
return e
}
if e = mon.Restart(o.x.GetContext()); e != nil {
return e
} else if e = o._setMonitor(mon); e != nil {
return e
}
return nil
}
func (o *componentRequest) _newMonitor(ctx context.Context, vrs libver.Version) (montps.Monitor, error) {
o.m.RLock()
defer o.m.RUnlock()
return o.r.Monitor(ctx, vrs)
}
func (o *componentRequest) _getMonitor(key string) montps.Monitor {
var (
mon montps.Monitor
pol = o._getMonitorPool()
)
if pol == nil {
return nil
}
mon = pol.MonitorGet(key)
return mon
}
func (o *componentRequest) _setMonitor(mon montps.Monitor) error {
var pol = o._getMonitorPool()
if pol == nil {
return nil
}
return pol.MonitorSet(mon)
}

View File

@@ -0,0 +1,233 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package smtp
import (
"context"
"crypto/tls"
libtls "github.com/nabbar/golib/certificates"
cpttls "github.com/nabbar/golib/config/components/tls"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
moncfg "github.com/nabbar/golib/monitor/types"
lbsmtp "github.com/nabbar/golib/smtp"
smtpcf "github.com/nabbar/golib/smtp/config"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentSmtp) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentSmtp) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentSmtp) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentSmtp) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentSmtp) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentSmtp) _getContext() context.Context {
o.m.RLock()
defer o.m.RUnlock()
return o.x.GetContext()
}
func (o *componentSmtp) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentSmtp) _GetTLS() libtls.TLSConfig {
o.m.RLock()
defer o.m.RUnlock()
if o.t == "" {
return nil
}
if i := cpttls.Load(o._getFctCpt(), o.t); i == nil {
return nil
} else if tls := i.GetTLS(); tls == nil {
return nil
} else {
return tls
}
}
func (o *componentSmtp) _GetTLSConfig(cfg libtls.Config) *tls.Config {
if i, e := cfg.NewFrom(o._GetTLS()); e != nil {
return &tls.Config{}
} else {
return i.TlsConfig("")
}
}
func (o *componentSmtp) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentSmtp) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentSmtp) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentSmtp) _runCli() liberr.Error {
var (
e error
err liberr.Error
prt = ErrorComponentReload
obj lbsmtp.SMTP
cfg smtpcf.Config
mon *moncfg.Config
)
if !o.IsStarted() {
prt = ErrorComponentStart
}
if cfg, mon, err = o._getConfig(); err != nil {
return prt.Error(err)
} else if obj, err = lbsmtp.New(cfg, o._GetTLSConfig(cfg.GetTls())); err != nil {
return prt.Error(err)
}
o.Stop()
o.m.Lock()
o.s = obj
o.m.Unlock()
if e = o._registerMonitor(mon); e != nil {
return prt.ErrorParent(e)
}
return nil
}
func (o *componentSmtp) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,171 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package smtp
import (
cpttls "github.com/nabbar/golib/config/components/tls"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "smtp"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentSmtp) Type() string {
return ComponentType
}
func (o *componentSmtp) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentSmtp) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentSmtp) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentSmtp) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o != nil && len(o.t) > 0 && o.s != nil
}
func (o *componentSmtp) IsRunning() bool {
if !o.IsStarted() {
return false
}
o.m.RLock()
defer o.m.RUnlock()
return o.s.Check(o.x.GetContext()) == nil
}
func (o *componentSmtp) Start() liberr.Error {
return o._run()
}
func (o *componentSmtp) Reload() liberr.Error {
return o._run()
}
func (o *componentSmtp) Stop() {
o.m.Lock()
defer o.m.Unlock()
if o.s != nil {
o.s.Close()
}
o.s = nil
return
}
func (o *componentSmtp) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = []string{cpttls.ComponentType}
if o == nil {
return def
} else if len(o.t) > 0 {
def = []string{o.t}
}
if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentSmtp) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentSmtp) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,89 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package smtp
import (
liberr "github.com/nabbar/golib/errors"
libmon "github.com/nabbar/golib/monitor/types"
smtpcf "github.com/nabbar/golib/smtp/config"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentSmtp) RegisterFlag(Command *spfcbr.Command) error {
var (
key string
vpr *spfvpr.Viper
)
if vpr = o._getSPFViper(); vpr == nil {
return ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
}
_ = Command.PersistentFlags().String(key+".dsn", "", "A DSN like string to describe the smtp connection. Format allowed is [user[:password]@][net[(addr)]]/tlsmode[?param1=value1&paramN=valueN] ")
if err := vpr.BindPFlag(key+".dsn", Command.PersistentFlags().Lookup(key+".dsn")); err != nil {
return err
}
return nil
}
func (o *componentSmtp) _getConfig() (smtpcf.Config, *libmon.Config, liberr.Error) {
var (
key string
cfg smtpcf.ConfigModel
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, nil, ErrorParamInvalid.ErrorParent(e)
}
if val := vpr.GetString(key + "dsn"); val != "" {
cfg.DSN = val
}
if err = cfg.Validate(); err != nil {
return nil, nil, ErrorConfigInvalid.Error(err)
}
if c, e := cfg.Config(); e != nil {
return nil, nil, e
} else {
return c, &cfg.Monitor, nil
}
}

View File

@@ -30,20 +30,15 @@ import (
"bytes"
"encoding/json"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
cpttls "github.com/nabbar/golib/config/components/tls"
liberr "github.com/nabbar/golib/errors"
libsmtp "github.com/nabbar/golib/smtp"
libsts "github.com/nabbar/golib/status/config"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgcst "github.com/nabbar/golib/config/const"
moncfg "github.com/nabbar/golib/monitor/types"
)
var _defaultConfig = []byte(`{
"dsn": "",
"tls": ` + string(cpttls.DefaultConfig(libcfg.JSONIndent)) + `,
"status": ` + string(libsts.DefaultConfig(libcfg.JSONIndent)) + `
"tls": ` + string(cpttls.DefaultConfig(cfgcst.JSONIndent)) + `,
"monitor": ` + string(moncfg.DefaultConfig(cfgcst.JSONIndent)) + `
}`)
func SetDefaultConfig(cfg []byte) {
@@ -52,58 +47,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgcst.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentSmtp) DefaultConfig(indent string) []byte {
func (o *componentSmtp) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentSmtp) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
_ = Command.PersistentFlags().String(c.key+".dsn", "", "A DSN like string to describe the smtp connection. Format allowed is [user[:password]@][net[(addr)]]/tlsmode[?param1=value1&paramN=valueN] ")
if err := Viper.BindPFlag(c.key+".dsn", Command.PersistentFlags().Lookup(c.key+".dsn")); err != nil {
return err
}
return nil
}
func (c *componentSmtp) _getConfig(getCfg libcfg.FuncComponentConfigGet) (libsmtp.ConfigModel, liberr.Error) {
var (
cfg = libsmtp.ConfigModel{}
vpr = c.vpr()
err liberr.Error
)
if e := getCfg(c.key, &cfg); e != nil {
return cfg, ErrorParamInvalid.Error(e)
}
if val := vpr.GetString(c.key + "dsn"); val != "" {
cfg.DSN = val
}
if err = cfg.Validate(); err != nil {
return cfg, ErrorConfigInvalid.Error(err)
}
cfg.RegisterDefaultTLS(func() libtls.TLSConfig {
var (
t libtls.TLSConfig
e liberr.Error
)
if t, e = c._GetTLS(); e != nil {
return t
} else {
return nil
}
})
return cfg, nil
}

View File

@@ -38,10 +38,8 @@ const (
ErrorParamInvalid
ErrorComponentNotInitialized
ErrorConfigInvalid
ErrorStartComponent
ErrorReloadComponent
ErrorDependencyTLSDefault
ErrorDependencyLogDefault
ErrorComponentStart
ErrorComponentReload
)
func init() {
@@ -61,14 +59,10 @@ func getMessage(code liberr.CodeError) (message string) {
return "this component seems to not be correctly initialized"
case ErrorConfigInvalid:
return "invalid component config"
case ErrorStartComponent:
case ErrorComponentStart:
return "cannot start component with config"
case ErrorReloadComponent:
case ErrorComponentReload:
return "cannot reload component with new config"
case ErrorDependencyTLSDefault:
return "cannot retrieve TLS Component"
case ErrorDependencyLogDefault:
return "cannot retrieve Logger Component"
}
return liberr.NullMessage

View File

@@ -31,38 +31,29 @@ import (
libcfg "github.com/nabbar/golib/config"
cpttls "github.com/nabbar/golib/config/components/tls"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
libsmtp "github.com/nabbar/golib/smtp"
libsts "github.com/nabbar/golib/status"
)
const (
ComponentType = "smtp"
lbsmtp "github.com/nabbar/golib/smtp"
)
type ComponentSMTP interface {
libcfg.Component
cfgtps.Component
SetTLSKey(tlsKey string)
GetSMTP() (libsmtp.SMTP, liberr.Error)
SetStatusRouter(sts libsts.RouteStatus, prefix string)
GetSMTP() (lbsmtp.SMTP, liberr.Error)
}
func New(tlsKey string) ComponentSMTP {
func New(ctx libctx.FuncContext, tlsKey string) ComponentSMTP {
if tlsKey == "" {
tlsKey = cpttls.ComponentType
}
return &componentSmtp{
ctx: nil,
get: nil,
fsa: nil,
fsb: nil,
fra: nil,
frb: nil,
m: sync.Mutex{},
t: tlsKey,
s: nil,
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
t: tlsKey,
s: nil,
}
}
@@ -70,11 +61,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentSMTP) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key, tlsKey string) {
cfg.ComponentSet(key, New(tlsKey))
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key, tlsKey string) {
cfg.ComponentSet(key, New(ctx, tlsKey))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentSMTP {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentSMTP {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentSMTP); !ok {

View File

@@ -29,214 +29,34 @@ package smtp
import (
"sync"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
cpttls "github.com/nabbar/golib/config/components/tls"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
montps "github.com/nabbar/golib/monitor/types"
libsmtp "github.com/nabbar/golib/smtp"
libsts "github.com/nabbar/golib/status"
)
type componentSmtp struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
m sync.RWMutex
x libctx.Config[uint8]
p montps.FuncPool
t string
s libsmtp.SMTP
}
func (c *componentSmtp) _CheckDep() bool {
return c != nil && c.t != ""
func (o *componentSmtp) SetTLSKey(tlsKey string) {
o.m.Lock()
defer o.m.Unlock()
o.t = tlsKey
}
func (c *componentSmtp) _GetTLS() (libtls.TLSConfig, liberr.Error) {
if !c._CheckDep() {
func (o *componentSmtp) GetSMTP() (libsmtp.SMTP, liberr.Error) {
if !o.IsStarted() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if i := cpttls.Load(c.get, c.t); i == nil {
return nil, ErrorDependencyTLSDefault.Error(nil)
} else if tls := i.GetTLS(); tls == nil {
return nil, ErrorDependencyTLSDefault.Error(nil)
} else {
return tls, nil
}
}
func (c *componentSmtp) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
if c.s != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
}
func (c *componentSmtp) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
return nil
}
func (c *componentSmtp) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
var (
err liberr.Error
cli libsmtp.SMTP
cfg libsmtp.ConfigModel
)
if cfg, err = c._getConfig(getCfg); err != nil {
return err
}
if cli, err = cfg.GetSMTP(); err != nil {
if c.s != nil {
return ErrorReloadComponent.Error(err)
}
return ErrorStartComponent.Error(err)
}
if c.s != nil {
_ = c.s.Close
}
c.s = cli
return nil
}
func (c *componentSmtp) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
if !c._CheckDep() {
return ErrorComponentNotInitialized.Error(nil)
}
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentSmtp) Type() string {
return ComponentType
}
func (c *componentSmtp) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentSmtp) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentSmtp) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentSmtp) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c._CheckDep() && c.s != nil
}
func (c *componentSmtp) IsRunning(atLeast bool) bool {
if !c.IsStarted() {
return false
}
c.m.Lock()
defer c.m.Unlock()
e := c.s.Check(c.ctx())
return e == nil
}
func (c *componentSmtp) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentSmtp) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentSmtp) Stop() {
if !c.IsStarted() {
return
}
c.m.Lock()
defer c.m.Unlock()
c.s.Close()
}
func (c *componentSmtp) Dependencies() []string {
c.m.Lock()
defer c.m.Unlock()
if !c._CheckDep() {
return []string{cpttls.ComponentType}
}
return []string{c.t}
}
func (c *componentSmtp) SetTLSKey(tlsKey string) {
c.m.Lock()
defer c.m.Unlock()
c.t = tlsKey
}
func (c *componentSmtp) GetSMTP() (libsmtp.SMTP, liberr.Error) {
if !c.IsStarted() {
return nil, ErrorComponentNotInitialized.Error(nil)
}
c.m.Lock()
defer c.m.Unlock()
return c.s.Clone(), nil
}
func (c *componentSmtp) SetStatusRouter(sts libsts.RouteStatus, prefix string) {
c.m.Lock()
defer c.m.Unlock()
c.s.StatusRouter(sts, prefix)
o.m.Lock()
defer o.m.Unlock()
return o.s.Clone(), nil
}

View File

@@ -0,0 +1,129 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package smtp
import (
"context"
libctx "github.com/nabbar/golib/context"
montps "github.com/nabbar/golib/monitor/types"
libver "github.com/nabbar/golib/version"
)
func (o *componentSmtp) RegisterMonitorPool(fct montps.FuncPool) {
o.m.Lock()
defer o.m.Unlock()
o.p = fct
}
func (o *componentSmtp) _getMonitorPool() montps.Pool {
o.m.RLock()
defer o.m.RUnlock()
if o.p == nil {
return nil
} else if p := o.p(); p == nil {
return nil
} else {
return p
}
}
func (o *componentSmtp) _registerMonitor(cfg *montps.Config) error {
var (
e error
key = o._getKey()
mon montps.Monitor
vrs = o._getVersion()
ctx = o._getContext
)
if o._getMonitorPool() == nil {
return nil
} else if len(key) < 1 {
return ErrorComponentNotInitialized.Error(nil)
} else if cfg == nil {
return ErrorConfigInvalid.Error(nil)
} else if !o.IsStarted() {
return ErrorComponentStart.Error(nil)
} else if ctx == nil {
ctx = context.Background
}
if mon = o._getMonitor(key); mon == nil {
if mon, e = o._newMonitor(ctx, vrs); e != nil {
return e
} else if mon == nil {
return nil
}
}
mon.RegisterLoggerDefault(o.getLogger)
if e = mon.SetConfig(o.x.GetContext, *cfg); e != nil {
return e
}
if e = mon.Restart(o.x.GetContext()); e != nil {
return e
} else if e = o._setMonitor(mon); e != nil {
return e
}
return nil
}
func (o *componentSmtp) _newMonitor(ctx libctx.FuncContext, vrs libver.Version) (montps.Monitor, error) {
o.m.RLock()
defer o.m.RUnlock()
return o.s.Monitor(ctx, vrs)
}
func (o *componentSmtp) _getMonitor(key string) montps.Monitor {
var (
mon montps.Monitor
pol = o._getMonitorPool()
)
if pol == nil {
return nil
}
mon = pol.MonitorGet(key)
return mon
}
func (o *componentSmtp) _setMonitor(mon montps.Monitor) error {
var pol = o._getMonitorPool()
if pol == nil {
return nil
}
return pol.MonitorSet(mon)
}

View File

@@ -0,0 +1,188 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package tls
import (
libtls "github.com/nabbar/golib/certificates"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvbr "github.com/spf13/viper"
)
func (o *componentTls) _getKey() string {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptKey); !l {
return ""
} else if i == nil {
return ""
} else if v, k := i.(string); !k {
return ""
} else {
return v
}
}
func (o *componentTls) _getFctVpr() libvpr.FuncViper {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctViper); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(libvpr.FuncViper); !k {
return nil
} else {
return f
}
}
func (o *componentTls) _getViper() libvpr.Viper {
if f := o._getFctVpr(); f == nil {
return nil
} else if v := f(); v == nil {
return nil
} else {
return v
}
}
func (o *componentTls) _getSPFViper() *spfvbr.Viper {
if f := o._getViper(); f == nil {
return nil
} else if v := f.Viper(); v == nil {
return nil
} else {
return v
}
}
func (o *componentTls) _getFctCpt() cfgtps.FuncCptGet {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyFctGetCpt); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptGet); !k {
return nil
} else {
return f
}
}
func (o *componentTls) _getVersion() libver.Version {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(keyCptVersion); !l {
return nil
} else if i == nil {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else {
return v
}
}
func (o *componentTls) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
if o.IsStarted() {
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
} else {
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
}
}
func (o *componentTls) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
o.m.RLock()
defer o.m.RUnlock()
if i, l := o.x.Load(key); !l {
return nil
} else if i == nil {
return nil
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
return nil
} else {
return f
}
}
func (o *componentTls) _runFct(fct func(cpt cfgtps.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(o)
}
return nil
}
func (o *componentTls) _runCli() liberr.Error {
var (
err liberr.Error
prt = ErrorComponentReload
tls libtls.TLSConfig
cfg *libtls.Config
)
if !o.IsStarted() {
prt = ErrorComponentStart
}
if cfg, err = o._getConfig(); err != nil {
return prt.Error(err)
} else if tls, err = cfg.New(); err != nil {
return prt.Error(err)
}
o.m.Lock()
defer o.m.Unlock()
o.t = tls
o.c = cfg
return nil
}
func (o *componentTls) _run() liberr.Error {
fb, fa := o._getFct()
if err := o._runFct(fb); err != nil {
return err
} else if err = o._runCli(); err != nil {
return err
} else if err = o._runFct(fa); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,155 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package tls
import (
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
const (
ComponentType = "tls"
keyCptKey = iota + 1
keyCptDependencies
keyFctViper
keyFctGetCpt
keyCptVersion
keyCptLogger
keyFctStaBef
keyFctStaAft
keyFctRelBef
keyFctRelAft
keyFctMonitorPool
)
func (o *componentTls) Type() string {
return ComponentType
}
func (o *componentTls) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
o.m.Lock()
defer o.m.Unlock()
if o.x == nil {
o.x = libctx.NewConfig[uint8](ctx)
} else {
x := libctx.NewConfig[uint8](ctx)
x.Merge(o.x)
o.x = x
}
o.x.Store(keyCptKey, key)
o.x.Store(keyFctGetCpt, get)
o.x.Store(keyFctViper, vpr)
o.x.Store(keyCptVersion, vrs)
o.x.Store(keyCptLogger, log)
}
func (o *componentTls) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctStaBef, before)
o.x.Store(keyFctStaAft, after)
}
func (o *componentTls) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
o.x.Store(keyFctRelBef, before)
o.x.Store(keyFctRelAft, after)
}
func (o *componentTls) IsStarted() bool {
o.m.RLock()
defer o.m.RUnlock()
return o.t != nil
}
func (o *componentTls) IsRunning() bool {
return o.IsStarted()
}
func (o *componentTls) Start() liberr.Error {
return o._run()
}
func (o *componentTls) Reload() liberr.Error {
return o._run()
}
func (o *componentTls) Stop() {
o.m.Lock()
defer o.m.Unlock()
o.t = nil
return
}
func (o *componentTls) Dependencies() []string {
o.m.RLock()
defer o.m.RUnlock()
var def = make([]string, 0)
if o == nil {
return def
} else if o.x == nil {
return def
} else if i, l := o.x.Load(keyCptDependencies); !l {
return def
} else if v, k := i.([]string); !k {
return def
} else if len(v) > 0 {
return v
} else {
return def
}
}
func (o *componentTls) SetDependencies(d []string) liberr.Error {
o.m.RLock()
defer o.m.RUnlock()
if o.x == nil {
return ErrorComponentNotInitialized.Error(nil)
} else {
o.x.Store(keyCptDependencies, d)
return nil
}
}
func (o *componentTls) getLogger() liblog.Logger {
if i, l := o.x.Load(keyCptLogger); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else {
return v()
}
}

View File

@@ -0,0 +1,63 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package tls
import (
libtls "github.com/nabbar/golib/certificates"
liberr "github.com/nabbar/golib/errors"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
func (o *componentTls) RegisterFlag(Command *spfcbr.Command) error {
return nil
}
func (o *componentTls) _getConfig() (*libtls.Config, liberr.Error) {
var (
key string
cfg libtls.Config
vpr *spfvpr.Viper
err liberr.Error
)
if vpr = o._getSPFViper(); vpr == nil {
return nil, ErrorComponentNotInitialized.Error(nil)
} else if key = o._getKey(); len(key) < 1 {
return nil, ErrorComponentNotInitialized.Error(nil)
}
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
return nil, ErrorParamInvalid.ErrorParent(e)
}
if err = cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -30,11 +30,7 @@ import (
"bytes"
"encoding/json"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
spfcbr "github.com/spf13/cobra"
spfvbr "github.com/spf13/viper"
cfgtps "github.com/nabbar/golib/config/const"
)
var _defaultConfig = []byte(`{
@@ -100,31 +96,13 @@ func SetDefaultConfig(cfg []byte) {
func DefaultConfig(indent string) []byte {
var res = bytes.NewBuffer(make([]byte, 0))
if err := json.Indent(res, _defaultConfig, indent, libcfg.JSONIndent); err != nil {
if err := json.Indent(res, _defaultConfig, indent, cfgtps.JSONIndent); err != nil {
return _defaultConfig
} else {
return res.Bytes()
}
}
func (c *componentTls) DefaultConfig(indent string) []byte {
func (o *componentTls) DefaultConfig(indent string) []byte {
return DefaultConfig(indent)
}
func (c *componentTls) RegisterFlag(Command *spfcbr.Command, Viper *spfvbr.Viper) error {
return nil
}
func (c *componentTls) _getConfig(getCfg libcfg.FuncComponentConfigGet) (*libtls.Config, liberr.Error) {
cfg := libtls.Config{}
if err := getCfg(c.key, &cfg); err != nil {
return nil, ErrorParamInvalid.Error(err)
}
if err := cfg.Validate(); err != nil {
return nil, ErrorConfigInvalid.Error(err)
}
return &cfg, nil
}

View File

@@ -27,24 +27,27 @@
package tls
import (
"sync"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
)
const (
ComponentType = "tls"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
)
type ComponentTlS interface {
libcfg.Component
cfgtps.Component
Config() *libtls.Config
GetTLS() libtls.TLSConfig
SetTLS(tls libtls.TLSConfig)
}
func New() ComponentTlS {
func New(ctx libctx.FuncContext) ComponentTlS {
return &componentTls{
m: sync.RWMutex{},
x: libctx.NewConfig[uint8](ctx),
t: nil,
c: nil,
}
}
@@ -52,11 +55,11 @@ func Register(cfg libcfg.Config, key string, cpt ComponentTlS) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New())
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string) {
cfg.ComponentSet(key, New(ctx))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentTlS {
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentTlS {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentTlS); !ok {

View File

@@ -30,158 +30,33 @@ import (
"sync"
libtls "github.com/nabbar/golib/certificates"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
libctx "github.com/nabbar/golib/context"
)
type componentTls struct {
ctx libcfg.FuncContext
get libcfg.FuncComponentGet
vpr libcfg.FuncComponentViper
key string
fsa func(cpt libcfg.Component) liberr.Error
fsb func(cpt libcfg.Component) liberr.Error
fra func(cpt libcfg.Component) liberr.Error
frb func(cpt libcfg.Component) liberr.Error
m sync.Mutex
m sync.RWMutex
x libctx.Config[uint8]
t libtls.TLSConfig
c *libtls.Config
}
func (c *componentTls) _getFct() (func(cpt libcfg.Component) liberr.Error, func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
func (o *componentTls) Config() *libtls.Config {
o.m.Lock()
defer o.m.Unlock()
if c.t != nil {
return c.frb, c.fra
} else {
return c.fsb, c.fsa
}
return o.c
}
func (c *componentTls) _runFct(fct func(cpt libcfg.Component) liberr.Error) liberr.Error {
if fct != nil {
return fct(c)
}
func (o *componentTls) GetTLS() libtls.TLSConfig {
o.m.Lock()
defer o.m.Unlock()
return nil
return o.t
}
func (c *componentTls) _runCli(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
c.m.Lock()
defer c.m.Unlock()
func (o *componentTls) SetTLS(tls libtls.TLSConfig) {
o.m.Lock()
defer o.m.Unlock()
var (
err liberr.Error
cfg *libtls.Config
tls libtls.TLSConfig
)
if cfg, err = c._getConfig(getCfg); err != nil {
return err
} else if tls, err = cfg.New(); err != nil {
if c.t != nil {
return ErrorComponentReload.Error(err)
}
return ErrorComponentStart.Error(err)
} else {
c.t = tls
c.c = cfg
}
return nil
}
func (c *componentTls) _run(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
fb, fa := c._getFct()
if err := c._runFct(fb); err != nil {
return err
} else if err = c._runCli(getCfg); err != nil {
return err
} else if err = c._runFct(fa); err != nil {
return err
}
return nil
}
func (c *componentTls) Type() string {
return ComponentType
}
func (c *componentTls) Init(key string, ctx libcfg.FuncContext, get libcfg.FuncComponentGet, vpr libcfg.FuncComponentViper, sts libcfg.FuncRouteStatus) {
c.m.Lock()
defer c.m.Unlock()
c.key = key
c.ctx = ctx
c.get = get
c.vpr = vpr
}
func (c *componentTls) RegisterFuncStart(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fsb = before
c.fsa = after
}
func (c *componentTls) RegisterFuncReload(before, after func(cpt libcfg.Component) liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.frb = before
c.fra = after
}
func (c *componentTls) IsStarted() bool {
c.m.Lock()
defer c.m.Unlock()
return c.t != nil
}
func (c *componentTls) IsRunning(atLeast bool) bool {
return c.IsStarted()
}
func (c *componentTls) Start(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentTls) Reload(getCfg libcfg.FuncComponentConfigGet) liberr.Error {
return c._run(getCfg)
}
func (c *componentTls) Stop() {
return
}
func (c *componentTls) Dependencies() []string {
return make([]string, 0)
}
func (c *componentTls) Config() *libtls.Config {
c.m.Lock()
defer c.m.Unlock()
return c.c
}
func (c *componentTls) GetTLS() libtls.TLSConfig {
c.m.Lock()
defer c.m.Unlock()
return c.t
}
func (c *componentTls) SetTLS(tls libtls.TLSConfig) {
c.m.Lock()
defer c.m.Unlock()
c.t = tls
o.t = tls
}

View File

@@ -0,0 +1,34 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package tls
import (
montps "github.com/nabbar/golib/monitor/types"
)
func (o *componentTls) RegisterMonitorPool(fct montps.FuncPool) {
}

31
config/const/const.go Normal file
View File

@@ -0,0 +1,31 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package _const
const (
JSONIndent = " "
)

65
config/context.go Normal file
View File

@@ -0,0 +1,65 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package config
import (
libctx "github.com/nabbar/golib/context"
)
func (c *configModel) Context() libctx.Config[string] {
return c.ctx
}
func (c *configModel) CancelAdd(fct ...func()) {
c.m.Lock()
defer c.m.Unlock()
c.fcnl = append(c.fcnl, fct...)
}
func (c *configModel) CancelClean() {
c.m.Lock()
defer c.m.Unlock()
c.fcnl = make([]func(), 0)
}
func (c *configModel) cancel() {
if l := c.getCancelCustom(); len(l) > 0 {
for _, f := range l {
f()
}
}
c.Stop()
}
func (c *configModel) getCancelCustom() []func() {
c.m.RLock()
defer c.m.RUnlock()
return c.fcnl
}

View File

@@ -1,414 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package config
import (
"bytes"
"encoding/json"
"fmt"
"io"
"sync"
"sync/atomic"
"time"
"golang.org/x/exp/slices"
liberr "github.com/nabbar/golib/errors"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
const JSONIndent = " "
type ComponentList interface {
// ComponentHas return true if the key is a registered Component
ComponentHas(key string) bool
// ComponentType return the Component Type of the registered key.
ComponentType(key string) string
// ComponentGet return the given component associated with the config Key.
// The component can be transTyped to other interface to be exploited
ComponentGet(key string) Component
// ComponentDel remove the given Component key from the config.
ComponentDel(key string)
// ComponentSet stores the given Component with a key.
ComponentSet(key string, cpt Component)
// ComponentList returns a map of stored couple keyType and Component
ComponentList() map[string]Component
// ComponentKeys returns a slice of stored Component keys
ComponentKeys() []string
// ComponentStart trigger the Start function of each Component.
// This function will keep the dependencies of each Component.
// This function will stop the Start sequence on any error triggered.
ComponentStart(getCfg FuncComponentConfigGet) liberr.Error
// ComponentIsStarted will trigger the IsStarted function of all registered component.
// If any component return false, this func return false.
ComponentIsStarted() bool
// ComponentReload trigger the Reload function of each Component.
// This function will keep the dependencies of each Component.
// This function will stop the Reload sequence on any error triggered.
ComponentReload(getCfg FuncComponentConfigGet) liberr.Error
// ComponentStop trigger the Stop function of each Component.
// This function will not keep the dependencies of each Component.
ComponentStop()
// ComponentIsRunning will trigger the IsRunning function of all registered component.
// If any component return false, this func return false.
ComponentIsRunning(atLeast bool) bool
// DefaultConfig aggregates all registered components' default config
// Returns a filled buffer with a complete config json model
DefaultConfig() io.Reader
// RegisterFlag can be called to register flag to a spf cobra command and link it with viper
// to retrieve it into the config viper.
// The key will be use to stay config organisation by compose flag as key.config_key.
RegisterFlag(Command *spfcbr.Command, Viper *spfvpr.Viper) error
}
func newComponentList() ComponentList {
return &componentList{
m: sync.Mutex{},
l: make(map[string]*atomic.Value, 0),
}
}
type componentList struct {
m sync.Mutex
l map[string]*atomic.Value
}
func (c *componentList) ComponentHas(key string) bool {
c.m.Lock()
defer c.m.Unlock()
_, ok := c.l[key]
return ok
}
func (c *componentList) ComponentType(key string) string {
if !c.ComponentHas(key) {
return ""
} else if o := c.ComponentGet(key); o == nil {
return ""
} else {
return o.Type()
}
}
func (c *componentList) ComponentGet(key string) Component {
if !c.ComponentHas(key) {
return nil
}
c.m.Lock()
defer c.m.Unlock()
if len(c.l) < 1 {
c.l = make(map[string]*atomic.Value, 0)
}
if v := c.l[key]; v == nil {
return nil
} else if i := v.Load(); i == nil {
return nil
} else if o, ok := i.(Component); !ok {
return nil
} else {
return o
}
}
func (c *componentList) ComponentDel(key string) {
if !c.ComponentHas(key) {
return
}
c.m.Lock()
defer c.m.Unlock()
if len(c.l) < 1 {
c.l = make(map[string]*atomic.Value, 0)
}
delete(c.l, key)
}
func (c *componentList) ComponentSet(key string, cpt Component) {
c.m.Lock()
defer c.m.Unlock()
if len(c.l) < 1 {
c.l = make(map[string]*atomic.Value, 0)
}
if v, ok := c.l[key]; !ok || v == nil {
c.l[key] = new(atomic.Value)
}
c.l[key].Store(cpt)
}
func (c *componentList) ComponentList() map[string]Component {
var res = make(map[string]Component, 0)
for _, k := range c.ComponentKeys() {
res[k] = c.ComponentGet(k)
}
return res
}
func (c *componentList) ComponentKeys() []string {
c.m.Lock()
defer c.m.Unlock()
var res = make([]string, 0)
for k := range c.l {
res = append(res, k)
}
return res
}
func (c *componentList) startOne(key string, getCfg FuncComponentConfigGet) liberr.Error {
var cpt Component
if !c.ComponentHas(key) {
return ErrorComponentNotFound.ErrorParent(fmt.Errorf("component: %s", key))
} else if cpt = c.ComponentGet(key); cpt == nil {
return ErrorComponentNotFound.ErrorParent(fmt.Errorf("component: %s", key))
} else if cpt.IsStarted() {
return nil
}
if dep := cpt.Dependencies(); len(dep) > 0 {
for _, k := range dep {
var err liberr.Error
for retry := 0; retry < 3; retry++ {
if err = c.startOne(k, getCfg); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
if err != nil {
return err
}
}
}
if err := cpt.Start(getCfg); err != nil {
return err
} else {
c.ComponentSet(key, cpt)
}
return nil
}
func (c *componentList) ComponentStart(getCfg FuncComponentConfigGet) liberr.Error {
for _, key := range c.ComponentKeys() {
if err := c.startOne(key, getCfg); err != nil {
return err
}
}
return nil
}
func (c *componentList) ComponentIsStarted() bool {
for _, k := range c.ComponentKeys() {
if cpt := c.ComponentGet(k); cpt == nil {
continue
} else if ok := cpt.IsStarted(); !ok {
return false
}
}
return true
}
func (c *componentList) reloadOne(isReload []string, key string, getCfg FuncComponentConfigGet) ([]string, liberr.Error) {
var (
err = ErrorComponentReload.Error(nil)
e liberr.Error
cpt Component
)
if !c.ComponentHas(key) {
return isReload, ErrorComponentNotFound.ErrorParent(fmt.Errorf("component: %s", key))
} else if cpt = c.ComponentGet(key); cpt == nil {
return isReload, ErrorComponentNotFound.ErrorParent(fmt.Errorf("component: %s", key))
} else if slices.Contains(isReload, key) {
return isReload, nil
}
if dep := cpt.Dependencies(); len(dep) > 0 {
for _, k := range dep {
if isReload, e = c.reloadOne(isReload, k, getCfg); e != nil {
err.AddParentError(e)
}
}
}
if e = cpt.Reload(getCfg); e != nil {
er := ErrorComponentReload.ErrorParent(fmt.Errorf("component: %s", key))
er.AddParentError(e)
err.AddParentError(er)
} else {
c.ComponentSet(key, cpt)
isReload = append(isReload, key)
}
if !err.HasParent() {
err = nil
}
return isReload, err
}
func (c *componentList) ComponentReload(getCfg FuncComponentConfigGet) liberr.Error {
var (
err = ErrorComponentReload.Error(nil)
e liberr.Error
key string
isReload = make([]string, 0)
)
for _, key = range c.ComponentKeys() {
if isReload, e = c.reloadOne(isReload, key, getCfg); e != nil {
err.AddParent(e)
}
}
if !err.HasParent() {
err = nil
}
return err
}
func (c *componentList) ComponentStop() {
for _, key := range c.ComponentKeys() {
if !c.ComponentHas(key) {
continue
}
cpt := c.ComponentGet(key)
if cpt == nil {
continue
}
cpt.Stop()
}
}
func (c *componentList) ComponentIsRunning(atLeast bool) bool {
for _, k := range c.ComponentKeys() {
if cpt := c.ComponentGet(k); cpt == nil {
continue
} else if ok := cpt.IsRunning(atLeast); !ok {
return false
}
}
return true
}
func (c *componentList) DefaultConfig() io.Reader {
var buffer = bytes.NewBuffer(make([]byte, 0))
buffer.WriteString("{")
buffer.WriteString("\n")
n := buffer.Len()
for _, k := range c.ComponentKeys() {
if cpt := c.ComponentGet(k); cpt == nil {
continue
} else if p := cpt.DefaultConfig(JSONIndent); len(p) > 0 {
if buffer.Len() > n {
buffer.WriteString(",")
buffer.WriteString("\n")
}
buffer.WriteString(fmt.Sprintf("%s\"%s\": ", JSONIndent, k))
buffer.Write(p)
}
}
buffer.WriteString("\n")
buffer.WriteString("}")
var (
cmp = bytes.NewBuffer(make([]byte, 0))
ind = bytes.NewBuffer(make([]byte, 0))
)
if err := json.Compact(cmp, buffer.Bytes()); err != nil {
return buffer
} else if err = json.Indent(ind, cmp.Bytes(), "", JSONIndent); err != nil {
return buffer
}
return ind
}
func (c *componentList) RegisterFlag(Command *spfcbr.Command, Viper *spfvpr.Viper) error {
var err = ErrorComponentFlagError.Error(nil)
for _, k := range c.ComponentKeys() {
if cpt := c.ComponentGet(k); cpt == nil {
continue
} else if e := cpt.RegisterFlag(Command, Viper); e != nil {
err.AddParent(e)
} else {
c.ComponentSet(k, cpt)
}
}
if err.HasParent() {
return err
}
return nil
}

View File

@@ -24,62 +24,53 @@
*
*/
package natsServer
package config
import (
"sync"
"os"
libcfg "github.com/nabbar/golib/config"
liberr "github.com/nabbar/golib/errors"
libnat "github.com/nabbar/golib/nats"
libsts "github.com/nabbar/golib/status"
)
const (
DefaultTlsKey = "tls"
ComponentType = "natsServer"
)
type ComponentNats interface {
libcfg.Component
SetTLSKey(tlsKey string)
GetServer() (libnat.Server, liberr.Error)
SetStatusRouter(sts libsts.RouteStatus, prefix string)
}
func New(tlsKey string) ComponentNats {
if tlsKey == "" {
tlsKey = DefaultTlsKey
func (c *configModel) Start() liberr.Error {
if err := c.runFuncStartBefore(); err != nil {
return err
}
return &componentNats{
ctx: nil,
get: nil,
fsa: nil,
fsb: nil,
fra: nil,
frb: nil,
m: sync.Mutex{},
t: tlsKey,
n: nil,
if err := c.ComponentStart(); err != nil {
return err
}
}
func Register(cfg libcfg.Config, key string, cpt ComponentNats) {
cfg.ComponentSet(key, cpt)
}
func RegisterNew(cfg libcfg.Config, key, tlsKey string) {
cfg.ComponentSet(key, New(tlsKey))
}
func Load(getCpt libcfg.FuncComponentGet, key string) ComponentNats {
if c := getCpt(key); c == nil {
return nil
} else if h, ok := c.(ComponentNats); !ok {
return nil
} else {
return h
if err := c.runFuncStartAfter(); err != nil {
return err
}
return nil
}
func (c *configModel) Reload() liberr.Error {
if err := c.runFuncReloadBefore(); err != nil {
return err
}
if err := c.ComponentReload(); err != nil {
return err
}
if err := c.runFuncReloadAfter(); err != nil {
return err
}
return nil
}
func (c *configModel) Stop() {
_ = c.runFuncStopBefore()
c.ComponentStop()
_ = c.runFuncStopAfter()
}
func (c *configModel) Shutdown(code int) {
c.cancel()
os.Exit(code)
}

View File

@@ -33,102 +33,96 @@ import (
"sync"
"syscall"
liblog "github.com/nabbar/golib/logger"
cfgtps "github.com/nabbar/golib/config/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
libsts "github.com/nabbar/golib/status"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvpr "github.com/spf13/viper"
)
type FuncContext func() context.Context
type FuncRouteStatus func() libsts.RouteStatus
type FuncComponentGet func(key string) Component
type FuncComponentViper func() *spfvpr.Viper
type FuncComponentConfigGet func(key string, model interface{}) liberr.Error
type FuncEvent func() liberr.Error
type Config interface {
/*
// Section Context : github.com/nabbar/golib/context
*/
// Context return the current context pointer
Context() context.Context
// Context return the config context instance
Context() libctx.Config[string]
// ContextMerge trigger the golib/context/config interface
// and will merge the stored context value into current context
ContextMerge(ctx libctx.Config) bool
// ContextStore trigger the golib/context/config interface
// and will store a context value into current context
ContextStore(key string, cfg interface{})
// ContextLoad trigger the golib/context/config interface
// and will restore a context value or nil
ContextLoad(key string) interface{}
// ContextSetCancel allow to register a custom function called on cancel context.
// CancelAdd allow to register a slice of custom function called on cancel context.
// On context cancel event or signal kill, term... this function will be called
// before config stop and main context cancel function
ContextSetCancel(fct func())
CancelAdd(fct ...func())
// CancelClean allow clear the all Cancel func registered into slice
CancelClean()
/*
// Section Event : github.com/nabbar/golib/config
// Section Manage : github.com/nabbar/golib/config
*/
// RegisterFuncViper is used to expose golib Viper instance to all config component.
// With this function, the component can load his own config part and start or reload.
RegisterFuncViper(fct func() libvpr.Viper)
// RegisterFuncRouteStatus is used to expose golib Status Router instance to all config component.
// With this function, the component can register component status for router status and expose his own health.
RegisterFuncRouteStatus(fct FuncRouteStatus)
// Start will trigger the start function of all registered component.
// If any component return an error, this func will stop the start
// process and return the error.
Start() liberr.Error
// RegisterFuncStartBefore allow to register a func to be call when the config Start
// is trigger. This func is call before the start sequence.
RegisterFuncStartBefore(fct func() liberr.Error)
// RegisterFuncStartAfter allow to register a func to be call when the config Start
// is trigger. This func is call after the start sequence.
RegisterFuncStartAfter(fct func() liberr.Error)
// Reload triggers the Reload function of each registered Component.
Reload() liberr.Error
// RegisterFuncReloadBefore allow to register a func to be call when the config Reload
// is trigger. This func is call before the reload sequence.
RegisterFuncReloadBefore(fct func() liberr.Error)
// RegisterFuncReloadAfter allow to register a func to be call when the config Reload
// is trigger. This func is call after the reload sequence.
RegisterFuncReloadAfter(fct func() liberr.Error)
// Stop will trigger the stop function of all registered component.
// All component must stop cleanly.
Stop()
// RegisterFuncStopBefore allow to register a func to be call when the config Stop
// is trigger. This func is call before the stop sequence.
RegisterFuncStopBefore(fct func())
// RegisterFuncStopAfter allow to register a func to be call when the config Stop
// is trigger. This func is call after the stop sequence.
RegisterFuncStopAfter(fct func())
// Shutdown will trigger all stop function.
// This function will call the Stop function and the private function cancel.
// This will stop all process and do like a SIGTERM/SIGINT signal.
// This will finish by an os.Exit with the given parameter code.
Shutdown(code int)
/*
// Section Events : github.com/nabbar/golib/config
*/
// RegisterFuncViper is used to expose golib Viper instance to all config component.
// With this function, the component can load his own config part and start or reload.
RegisterFuncViper(fct libvpr.FuncViper)
// RegisterFuncStartBefore allow to register a func to be call when the config Start
// is trigger. This func is call before the start sequence.
RegisterFuncStartBefore(fct FuncEvent)
// RegisterFuncStartAfter allow to register a func to be call when the config Start
// is trigger. This func is call after the start sequence.
RegisterFuncStartAfter(fct FuncEvent)
// RegisterFuncReloadBefore allow to register a func to be call when the config Reload
// is trigger. This func is call before the reload sequence.
RegisterFuncReloadBefore(fct FuncEvent)
// RegisterFuncReloadAfter allow to register a func to be call when the config Reload
// is trigger. This func is call after the reload sequence.
RegisterFuncReloadAfter(fct FuncEvent)
// RegisterFuncStopBefore allow to register a func to be call when the config Stop
// is trigger. This func is call before the stop sequence.
RegisterFuncStopBefore(fct FuncEvent)
// RegisterFuncStopAfter allow to register a func to be call when the config Stop
// is trigger. This func is call after the stop sequence.
RegisterFuncStopAfter(fct FuncEvent)
// RegisterDefaultLogger allow to register a func to return a default logger.
// This logger can be used by component to extend config ot to log message.
RegisterDefaultLogger(fct liblog.FuncLog)
/*
// Section Component : github.com/nabbar/golib/config
*/
ComponentList
cfgtps.ComponentList
cfgtps.ComponentMonitor
}
var (
@@ -138,30 +132,42 @@ var (
func init() {
ctx, cnl = context.WithCancel(context.Background())
go func() {
// Wait for interrupt signal to gracefully shutdown the server with
// a timeout of 5 seconds.
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT)
signal.Notify(quit, syscall.SIGTERM)
signal.Notify(quit, syscall.SIGQUIT)
select {
case <-quit:
cnl()
case <-ctx.Done():
cnl()
}
}()
}
func New() Config {
c := &configModel{
m: sync.Mutex{},
ctx: libctx.NewConfig(ctx),
cpt: newComponentList(),
func Shutdown() {
cnl()
}
func WaitNotify() {
// Wait for interrupt signal to gracefully shutdown the server with
// a timeout of 5 seconds.
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT)
signal.Notify(quit, syscall.SIGTERM)
signal.Notify(quit, syscall.SIGQUIT)
select {
case <-quit:
cnl()
case <-ctx.Done():
cnl()
}
}
func New(vrs libver.Version) Config {
fct := func() context.Context {
return ctx
}
c := &configModel{
m: sync.RWMutex{},
ctx: libctx.NewConfig[string](fct),
cpt: libctx.NewConfig[string](fct),
fct: libctx.NewConfig[uint8](fct),
fcnl: nil,
}
c.RegisterVersion(vrs)
go func() {
select {

216
config/manage.go Normal file
View File

@@ -0,0 +1,216 @@
/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package config
import (
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
montps "github.com/nabbar/golib/monitor/types"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
spfvpr "github.com/spf13/viper"
)
func (c *configModel) RegisterVersion(vrs libver.Version) {
c.fct.Store(fctVersion, vrs)
}
func (c *configModel) getVersion() libver.Version {
if i, l := c.fct.Load(fctVersion); !l {
return nil
} else if v, k := i.(libver.Version); !k {
return nil
} else if v == nil {
return nil
} else {
return v
}
}
func (c *configModel) RegisterFuncViper(fct libvpr.FuncViper) {
c.fct.Store(fctViper, fct)
}
func (c *configModel) getViper() libvpr.Viper {
if i, l := c.fct.Load(fctViper); !l {
return nil
} else if v, k := i.(libvpr.FuncViper); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) getSPFViper() *spfvpr.Viper {
if v := c.getViper(); v == nil {
return nil
} else {
return v.Viper()
}
}
func (c *configModel) RegisterFuncStartBefore(fct FuncEvent) {
c.fct.Store(fctStartBefore, fct)
}
func (c *configModel) runFuncStartBefore() liberr.Error {
if i, l := c.fct.Load(fctStartBefore); !l {
return nil
} else if v, k := i.(FuncEvent); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) RegisterFuncStartAfter(fct FuncEvent) {
c.fct.Store(fctStartAfter, fct)
}
func (c *configModel) runFuncStartAfter() liberr.Error {
if i, l := c.fct.Load(fctStartAfter); !l {
return nil
} else if v, k := i.(FuncEvent); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) RegisterFuncReloadBefore(fct FuncEvent) {
c.fct.Store(fctReloadBefore, fct)
}
func (c *configModel) runFuncReloadBefore() liberr.Error {
if i, l := c.fct.Load(fctReloadBefore); !l {
return nil
} else if v, k := i.(FuncEvent); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) RegisterFuncReloadAfter(fct FuncEvent) {
c.fct.Store(fctReloadAfter, fct)
}
func (c *configModel) runFuncReloadAfter() liberr.Error {
if i, l := c.fct.Load(fctReloadAfter); !l {
return nil
} else if v, k := i.(FuncEvent); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) RegisterFuncStopBefore(fct FuncEvent) {
c.fct.Store(fctStopBefore, fct)
}
func (c *configModel) runFuncStopBefore() liberr.Error {
if i, l := c.fct.Load(fctStopBefore); !l {
return nil
} else if v, k := i.(FuncEvent); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) RegisterFuncStopAfter(fct FuncEvent) {
c.fct.Store(fctStopAfter, fct)
}
func (c *configModel) runFuncStopAfter() liberr.Error {
if i, l := c.fct.Load(fctStopAfter); !l {
return nil
} else if v, k := i.(FuncEvent); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) RegisterDefaultLogger(fct liblog.FuncLog) {
c.fct.Store(fctLoggerDef, fct)
}
func (c *configModel) getDefaultLogger() liblog.Logger {
if i, l := c.fct.Load(fctLoggerDef); !l {
return nil
} else if v, k := i.(liblog.FuncLog); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}
func (c *configModel) RegisterMonitorPool(p montps.FuncPool) {
c.fct.Store(fctMonitorPool, p)
}
func (c *configModel) getFctMonitorPool() montps.FuncPool {
if i, l := c.fct.Load(fctMonitorPool); !l {
return nil
} else if v, k := i.(montps.FuncPool); !k {
return nil
} else if v == nil {
return nil
} else {
return v
}
}
func (c *configModel) getMonitorPool() montps.Pool {
if i, l := c.fct.Load(fctMonitorPool); !l {
return nil
} else if v, k := i.(montps.FuncPool); !k {
return nil
} else if v == nil {
return nil
} else {
return v()
}
}

View File

@@ -27,279 +27,43 @@
package config
import (
"context"
"fmt"
"io"
"os"
"sync"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
libvpr "github.com/nabbar/golib/viper"
spfcbr "github.com/spf13/cobra"
spfvpr "github.com/spf13/viper"
)
const (
fctViper uint8 = iota + 1
fctStartBefore
fctStartAfter
fctReloadBefore
fctReloadAfter
fctStopBefore
fctStopAfter
fctVersion
fctLoggerDef
fctMonitorPool
)
type configModel struct {
m sync.Mutex
m sync.RWMutex
ctx libctx.Config
fcnl func()
ctx libctx.Config[string]
cpt libctx.Config[string]
fct libctx.Config[uint8]
cpt ComponentList
fctGolibStatus FuncRouteStatus
fctGolibViper func() libvpr.Viper
fctStartBefore func() liberr.Error
fctStartAfter func() liberr.Error
fctReloadBefore func() liberr.Error
fctReloadAfter func() liberr.Error
fctStopBefore func()
fctStopAfter func()
fcnl []func()
}
func (c *configModel) _ComponentGetConfig(key string, model interface{}) liberr.Error {
var (
err error
vpr libvpr.Viper
vip *spfvpr.Viper
)
if c.cpt.ComponentHas(key) {
if c.fctGolibViper == nil {
return ErrorConfigMissingViper.Error(nil)
} else if vpr = c.fctGolibViper(); vpr == nil {
return ErrorConfigMissingViper.Error(nil)
} else if vip = vpr.Viper(); vip == nil {
return ErrorConfigMissingViper.Error(nil)
}
err = vip.UnmarshalKey(key, model)
} else {
return ErrorComponentNotFound.ErrorParent(fmt.Errorf("component '%s'", key))
}
return ErrorComponentConfigError.Iferror(err)
}
func (c *configModel) Context() context.Context {
return c.ctx
}
func (c *configModel) ContextMerge(ctx libctx.Config) bool {
return c.ctx.Merge(ctx)
}
func (c *configModel) ContextStore(key string, cfg interface{}) {
c.ctx.Store(key, cfg)
}
func (c *configModel) ContextLoad(key string) interface{} {
return c.ctx.Load(key)
}
func (c *configModel) ContextSetCancel(fct func()) {
c.m.Lock()
defer c.m.Unlock()
c.fcnl = fct
}
func (c *configModel) cancel() {
c.cancelCustom()
c.Stop()
}
func (c *configModel) cancelCustom() {
c.m.Lock()
defer c.m.Unlock()
if c.fcnl != nil {
c.fcnl()
}
}
func (c *configModel) RegisterFuncViper(fct func() libvpr.Viper) {
c.fctGolibViper = fct
}
func (c *configModel) RegisterFuncRouteStatus(fct FuncRouteStatus) {
c.fctGolibStatus = fct
}
func (c *configModel) Start() liberr.Error {
c.m.Lock()
defer c.m.Unlock()
if c.fctStartBefore != nil {
if err := c.fctStartBefore(); err != nil {
return err
}
}
if err := c.cpt.ComponentStart(c._ComponentGetConfig); err != nil {
return err
}
if c.fctStartAfter != nil {
if err := c.fctStartAfter(); err != nil {
return err
}
if vpr := c.getViper(); vpr == nil {
return ErrorConfigMissingViper.Error(nil)
} else if vip := vpr.Viper(); vip == nil {
return ErrorConfigMissingViper.Error(nil)
} else if err := vpr.Viper().UnmarshalKey(key, model); err != nil {
return ErrorComponentConfigError.ErrorParent(err)
}
return nil
}
func (c *configModel) RegisterFuncStartBefore(fct func() liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fctStartBefore = fct
}
func (c *configModel) RegisterFuncStartAfter(fct func() liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fctStartAfter = fct
}
func (c *configModel) Reload() liberr.Error {
c.m.Lock()
defer c.m.Unlock()
if c.fctReloadBefore != nil {
if err := c.fctReloadBefore(); err != nil {
return err
}
}
if err := c.cpt.ComponentReload(c._ComponentGetConfig); err != nil {
return err
}
if c.fctReloadAfter != nil {
if err := c.fctReloadAfter(); err != nil {
return err
}
}
return nil
}
func (c *configModel) RegisterFuncReloadBefore(fct func() liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fctReloadBefore = fct
}
func (c *configModel) RegisterFuncReloadAfter(fct func() liberr.Error) {
c.m.Lock()
defer c.m.Unlock()
c.fctReloadAfter = fct
}
func (c *configModel) Stop() {
c.m.Lock()
defer c.m.Unlock()
if c.fctStopBefore != nil {
c.fctStopBefore()
}
for _, k := range c.ComponentKeys() {
cpt := c.ComponentGet(k)
if cpt == nil {
continue
}
cpt.Stop()
}
if c.fctStopAfter != nil {
c.fctStopAfter()
}
}
func (c *configModel) RegisterFuncStopBefore(fct func()) {
c.m.Lock()
defer c.m.Unlock()
c.fctStopBefore = fct
}
func (c *configModel) RegisterFuncStopAfter(fct func()) {
c.m.Lock()
defer c.m.Unlock()
c.fctStopAfter = fct
}
func (c *configModel) Shutdown(code int) {
c.cancel()
os.Exit(code)
}
func (c *configModel) ComponentHas(key string) bool {
return c.cpt.ComponentHas(key)
}
func (c *configModel) ComponentType(key string) string {
return c.cpt.ComponentType(key)
}
func (c *configModel) ComponentGet(key string) Component {
return c.cpt.ComponentGet(key)
}
func (c *configModel) ComponentDel(key string) {
c.cpt.ComponentDel(key)
}
func (c *configModel) ComponentSet(key string, cpt Component) {
fv := func() *spfvpr.Viper {
if c.fctGolibViper == nil {
return nil
} else if vpr := c.fctGolibViper(); vpr == nil {
return nil
} else {
return vpr.Viper()
}
}
cpt.Init(key, c.Context, c.ComponentGet, fv, c.fctGolibStatus)
c.cpt.ComponentSet(key, cpt)
}
func (c *configModel) ComponentList() map[string]Component {
return c.cpt.ComponentList()
}
func (c *configModel) ComponentKeys() []string {
return c.cpt.ComponentKeys()
}
func (c *configModel) ComponentStart(getCfg FuncComponentConfigGet) liberr.Error {
return c.cpt.ComponentStart(getCfg)
}
func (c *configModel) ComponentIsStarted() bool {
return c.cpt.ComponentIsStarted()
}
func (c *configModel) ComponentReload(getCfg FuncComponentConfigGet) liberr.Error {
return c.cpt.ComponentReload(getCfg)
}
func (c *configModel) ComponentStop() {
c.cpt.ComponentStop()
}
func (c *configModel) ComponentIsRunning(atLeast bool) bool {
return c.cpt.ComponentIsRunning(atLeast)
}
func (c *configModel) DefaultConfig() io.Reader {
return c.cpt.DefaultConfig()
}
func (c *configModel) RegisterFlag(Command *spfcbr.Command, Viper *spfvpr.Viper) error {
return c.cpt.RegisterFlag(Command, Viper)
}

Some files were not shown because too many files have changed in this diff Show More