Package Status:

- Rework for the management of mandatory components to qualify the global status.
- Added qualification to components: "should", "must", "one of".
- These qualifications will influence the overall state but not the unitary state of each component.

Package Socket:
- Creation package to open and listen local unix file socket
- Allow to specify a handler who's needing a conn instance as entry
- Create a client sub package to allow negociate with the local unix file socket

Package Shell:
- adding sub package for command and command collection

Package Monitor:
- add function to expose monitor command for shell

Package Config:
- add function to expose monitor command for shell

Package Network:
- Add "IP" protocol

Pakcage Httpcli:
- Rework the construction of the client
- Add capability to specify proxy url

Package Cobra:
- add function to add flag to global command like verbose or config

Package Log:
- fix seg fault when calling a nil instance
- remove println in hookfile / hooksyslog
This commit is contained in:
Nicolas JUHEL
2023-07-24 09:03:08 +02:00
committed by nabbar
parent bb2f7f55c7
commit 7cd4eadc50
52 changed files with 2371 additions and 260 deletions

View File

@@ -43,19 +43,19 @@ import (
"testing"
"time"
"github.com/hashicorp/go-uuid"
"github.com/nabbar/golib/aws"
"github.com/nabbar/golib/aws/configCustom"
"github.com/nabbar/golib/httpcli"
"github.com/nabbar/golib/password"
lbuuid "github.com/hashicorp/go-uuid"
libaws "github.com/nabbar/golib/aws"
awscfg "github.com/nabbar/golib/aws/configCustom"
libhtc "github.com/nabbar/golib/httpcli"
libpwd "github.com/nabbar/golib/password"
libsiz "github.com/nabbar/golib/size"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var (
cli aws.AWS
cfg aws.Config
cli libaws.AWS
cfg libaws.Config
ctx context.Context
cnl context.CancelFunc
filename = "./config.json"
@@ -88,14 +88,15 @@ var _ = BeforeSuite(func() {
Host: "localhost:" + strconv.Itoa(GetFreePort()),
}
accessKey = password.Generate(20)
secretKey = password.Generate(64)
accessKey = libpwd.Generate(20)
secretKey = libpwd.Generate(64)
)
htp = httpcli.GetClient(uri.Hostname())
htp, err = libhtc.GetClient(libhtc.GetTransport(false, false, false), true, libhtc.ClientTimeout30Sec)
Expect(err).NotTo(HaveOccurred())
Expect(htp).NotTo(BeNil())
cfg = configCustom.NewConfig("", accessKey, secretKey, uri, "us-east-1")
cfg = awscfg.NewConfig("", accessKey, secretKey, uri, "us-east-1")
Expect(cfg).NotTo(BeNil())
cfg.SetRegion("us-east-1")
@@ -114,13 +115,13 @@ var _ = BeforeSuite(func() {
println("Minio is waiting on : " + uri.Host)
}
cli, err = aws.New(ctx, cfg, htp)
cli, err = libaws.New(ctx, cfg, htp)
Expect(err).NotTo(HaveOccurred())
Expect(cli).NotTo(BeNil())
cli.ForcePathStyle(ctx, true)
name, err = uuid.GenerateUUID()
name, err = lbuuid.GenerateUUID()
Expect(err).ToNot(HaveOccurred())
Expect(name).ToNot(BeEmpty())
cli.Config().SetBucketName(name)
@@ -144,7 +145,7 @@ func loadConfig() error {
return err
}
if cfg, err = configCustom.NewConfigJsonUnmashal(cnfByt); err != nil {
if cfg, err = awscfg.NewConfigJsonUnmashal(cnfByt); err != nil {
return err
}

View File

@@ -28,6 +28,7 @@ package cobra
import (
"io"
"time"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
@@ -53,6 +54,30 @@ type Cobra interface {
SetFlagConfig(persistent bool, flagVar *string) error
SetFlagVerbose(persistent bool, flagVar *int)
AddFlagString(persistent bool, p *string, name, shorthand string, value string, usage string)
AddFlagCount(persistent bool, p *int, name, shorthand string, usage string)
AddFlagBool(persistent bool, p *bool, name, shorthand string, value bool, usage string)
AddFlagDuration(persistent bool, p *time.Duration, name, shorthand string, value time.Duration, usage string)
AddFlagFloat32(persistent bool, p *float32, name, shorthand string, value float32, usage string)
AddFlagFloat64(persistent bool, p *float64, name, shorthand string, value float64, usage string)
AddFlagInt(persistent bool, p *int, name, shorthand string, value int, usage string)
AddFlagInt8(persistent bool, p *int8, name, shorthand string, value int8, usage string)
AddFlagInt16(persistent bool, p *int16, name, shorthand string, value int16, usage string)
AddFlagInt32(persistent bool, p *int32, name, shorthand string, value int32, usage string)
AddFlagInt32Slice(persistent bool, p *[]int32, name, shorthand string, value []int32, usage string)
AddFlagInt64(persistent bool, p *int64, name, shorthand string, value int64, usage string)
AddFlagInt64Slice(persistent bool, p *[]int64, name, shorthand string, value []int64, usage string)
AddFlagUint(persistent bool, p *uint, name, shorthand string, value uint, usage string)
AddFlagUintSlice(persistent bool, p *[]uint, name, shorthand string, value []uint, usage string)
AddFlagUint8(persistent bool, p *uint8, name, shorthand string, value uint8, usage string)
AddFlagUint16(persistent bool, p *uint16, name, shorthand string, value uint16, usage string)
AddFlagUint32(persistent bool, p *uint32, name, shorthand string, value uint32, usage string)
AddFlagUint64(persistent bool, p *uint64, name, shorthand string, value uint64, usage string)
AddFlagStringArray(persistent bool, p *[]string, name, shorthand string, value []string, usage string)
AddFlagStringToInt(persistent bool, p *map[string]int, name, shorthand string, value map[string]int, usage string)
AddFlagStringToInt64(persistent bool, p *map[string]int64, name, shorthand string, value map[string]int64, usage string)
AddFlagStringToString(persistent bool, p *map[string]string, name, shorthand string, value map[string]string, usage string)
NewCommand(cmd, short, long, useWithoutCmd, exampleWithoutCmd string) *spfcbr.Command
AddCommand(subCmd ...*spfcbr.Command)

View File

@@ -32,6 +32,7 @@ import (
"os"
"path/filepath"
"strings"
"time"
liblog "github.com/nabbar/golib/logger"
libver "github.com/nabbar/golib/version"
@@ -175,3 +176,187 @@ func (c *cobra) getPackageDescShort() string {
func (c *cobra) getPackageDescLong() string {
return c.s.GetDescription()
}
func (c *cobra) AddFlagString(persistent bool, p *string, name, shorthand string, value string, usage string) {
if persistent {
c.c.PersistentFlags().StringVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().StringVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagCount(persistent bool, p *int, name, shorthand string, usage string) {
if persistent {
c.c.PersistentFlags().CountVarP(p, name, shorthand, usage)
} else {
c.c.Flags().CountVarP(p, name, shorthand, usage)
}
}
func (c *cobra) AddFlagBool(persistent bool, p *bool, name, shorthand string, value bool, usage string) {
if persistent {
c.c.PersistentFlags().BoolVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().BoolVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagDuration(persistent bool, p *time.Duration, name, shorthand string, value time.Duration, usage string) {
if persistent {
c.c.PersistentFlags().DurationVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().DurationVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagFloat32(persistent bool, p *float32, name, shorthand string, value float32, usage string) {
if persistent {
c.c.PersistentFlags().Float32VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Float32VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagFloat64(persistent bool, p *float64, name, shorthand string, value float64, usage string) {
if persistent {
c.c.PersistentFlags().Float64VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Float64VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagInt(persistent bool, p *int, name, shorthand string, value int, usage string) {
if persistent {
c.c.PersistentFlags().IntVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().IntVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagInt8(persistent bool, p *int8, name, shorthand string, value int8, usage string) {
if persistent {
c.c.PersistentFlags().Int8VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Int8VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagInt16(persistent bool, p *int16, name, shorthand string, value int16, usage string) {
if persistent {
c.c.PersistentFlags().Int16VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Int16VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagInt32(persistent bool, p *int32, name, shorthand string, value int32, usage string) {
if persistent {
c.c.PersistentFlags().Int32VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Int32VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagInt32Slice(persistent bool, p *[]int32, name, shorthand string, value []int32, usage string) {
if persistent {
c.c.PersistentFlags().Int32SliceVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Int32SliceVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagInt64(persistent bool, p *int64, name, shorthand string, value int64, usage string) {
if persistent {
c.c.PersistentFlags().Int64VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Int64VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagInt64Slice(persistent bool, p *[]int64, name, shorthand string, value []int64, usage string) {
if persistent {
c.c.PersistentFlags().Int64SliceVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Int64SliceVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagUint(persistent bool, p *uint, name, shorthand string, value uint, usage string) {
if persistent {
c.c.PersistentFlags().UintVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().UintVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagUintSlice(persistent bool, p *[]uint, name, shorthand string, value []uint, usage string) {
if persistent {
c.c.PersistentFlags().UintSliceVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().UintSliceVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagUint8(persistent bool, p *uint8, name, shorthand string, value uint8, usage string) {
if persistent {
c.c.PersistentFlags().Uint8VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Uint8VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagUint16(persistent bool, p *uint16, name, shorthand string, value uint16, usage string) {
if persistent {
c.c.PersistentFlags().Uint16VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Uint16VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagUint32(persistent bool, p *uint32, name, shorthand string, value uint32, usage string) {
if persistent {
c.c.PersistentFlags().Uint32VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Uint32VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagUint64(persistent bool, p *uint64, name, shorthand string, value uint64, usage string) {
if persistent {
c.c.PersistentFlags().Uint64VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().Uint64VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagStringArray(persistent bool, p *[]string, name, shorthand string, value []string, usage string) {
if persistent {
c.c.PersistentFlags().StringArrayVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().StringArrayVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagStringToInt(persistent bool, p *map[string]int, name, shorthand string, value map[string]int, usage string) {
if persistent {
c.c.PersistentFlags().StringToIntVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().StringToIntVarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagStringToInt64(persistent bool, p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
if persistent {
c.c.PersistentFlags().StringToInt64VarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().StringToInt64VarP(p, name, shorthand, value, usage)
}
}
func (c *cobra) AddFlagStringToString(persistent bool, p *map[string]string, name, shorthand string, value map[string]string, usage string) {
if persistent {
c.c.PersistentFlags().StringToStringVarP(p, name, shorthand, value, usage)
} else {
c.c.Flags().StringToStringVarP(p, name, shorthand, value, usage)
}
}

View File

@@ -32,13 +32,11 @@ import (
"fmt"
"io"
"golang.org/x/exp/slices"
_const "github.com/nabbar/golib/config/const"
cfgcst "github.com/nabbar/golib/config/const"
cfgtps "github.com/nabbar/golib/config/types"
liberr "github.com/nabbar/golib/errors"
spfcbr "github.com/spf13/cobra"
"golang.org/x/exp/slices"
)
func (c *configModel) ComponentHas(key string) bool {
@@ -184,17 +182,19 @@ func (c *configModel) ComponentReload() liberr.Error {
}
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()
}
lst := c.ComponentDependencies()
return true
})
for i := len(lst) - 1; i >= 0; i-- {
key := lst[i]
if len(key) < 1 {
continue
} else if cpt := c.ComponentGet(key); cpt == nil {
continue
} else {
cpt.Stop()
}
}
}
func (c *configModel) ComponentIsRunning(atLeast bool) bool {
@@ -300,12 +300,12 @@ func (c *configModel) DefaultConfig() io.Reader {
return true
}
if p := v.DefaultConfig(_const.JSONIndent); len(p) > 0 {
if p := v.DefaultConfig(cfgcst.JSONIndent); len(p) > 0 {
if buffer.Len() > n {
buffer.WriteString(",")
buffer.WriteString("\n")
}
buffer.WriteString(fmt.Sprintf("%s\"%s\": ", _const.JSONIndent, key))
buffer.WriteString(fmt.Sprintf("%s\"%s\": ", cfgcst.JSONIndent, key))
buffer.Write(p)
}
@@ -322,7 +322,7 @@ func (c *configModel) DefaultConfig() io.Reader {
if err := json.Compact(cmp, buffer.Bytes()); err != nil {
return buffer
} else if err = json.Indent(ind, cmp.Bytes(), "", _const.JSONIndent); err != nil {
} else if err = json.Indent(ind, cmp.Bytes(), "", cfgcst.JSONIndent); err != nil {
return buffer
}

View File

@@ -33,11 +33,11 @@ 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"
liblog "github.com/nabbar/golib/logger"
shlcmd "github.com/nabbar/golib/shell/command"
libver "github.com/nabbar/golib/version"
libvpr "github.com/nabbar/golib/viper"
)
@@ -123,6 +123,11 @@ type Config interface {
*/
cfgtps.ComponentList
cfgtps.ComponentMonitor
/*
// Section Shell Command : github.com/nabbar/golib/shell
*/
GetShellCommand() []shlcmd.Command
}
var (

152
config/shell.go Normal file
View File

@@ -0,0 +1,152 @@
/*
* 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 (
"fmt"
"io"
shlcmd "github.com/nabbar/golib/shell/command"
)
func ShellCommandInfo() []shlcmd.CommandInfo {
var res = make([]shlcmd.CommandInfo, 0)
res = append(res, shlcmd.Info("list", "list all components"))
res = append(res, shlcmd.Info("start", "Starting components (leave args empty to start all components)"))
res = append(res, shlcmd.Info("stop", "Stopping components (leave args empty to start all components)"))
res = append(res, shlcmd.Info("restart", "Restarting (stop, start) components (leave args empty to restart all components)"))
return res
}
func (c *configModel) GetShellCommand() []shlcmd.Command {
var res = make([]shlcmd.Command, 0)
res = append(res, shlcmd.New("list", "list all components", func(buf io.Writer, err io.Writer, args []string) {
for _, key := range c.ComponentDependencies() {
if len(key) < 1 {
continue
} else if cpt := c.ComponentGet(key); cpt == nil {
continue
} else {
_, _ = fmt.Fprintln(buf, key)
}
}
}))
res = append(res, shlcmd.New("start", "Starting components (leave args empty to start all components)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = c.ComponentDependencies()
}
for _, key := range list {
if len(key) < 1 {
continue
} else if cpt := c.ComponentGet(key); cpt == nil {
continue
} else {
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Starting component '%s'", key))
e := cpt.Start()
c.componentUpdate(key, cpt)
if e != nil {
_, _ = fmt.Fprintln(err, e)
} else if !cpt.IsStarted() {
_, _ = fmt.Fprintln(err, fmt.Errorf("component is not started"))
}
}
}
}))
res = append(res, shlcmd.New("stop", "Stopping components (leave args empty to start all components)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = c.ComponentDependencies()
}
for i := len(list) - 1; i >= 0; i-- {
key := list[i]
if len(key) < 1 {
continue
} else if cpt := c.ComponentGet(key); cpt == nil {
continue
} else {
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Stopping component '%s'", key))
cpt.Stop()
}
}
}))
res = append(res, shlcmd.New("restart", "Restarting (stop, start) components (leave args empty to restart all components)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = c.ComponentDependencies()
}
for i := len(list) - 1; i >= 0; i-- {
key := list[i]
if len(key) < 1 {
continue
} else if cpt := c.ComponentGet(key); cpt == nil {
continue
} else {
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Stopping component '%s'", key))
cpt.Stop()
}
}
_, _ = fmt.Fprintln(buf, "")
for _, key := range list {
if len(key) < 1 {
continue
} else if cpt := c.ComponentGet(key); cpt == nil {
continue
} else {
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Starting component '%s'", key))
e := cpt.Start()
c.componentUpdate(key, cpt)
if e != nil {
_, _ = fmt.Fprintln(err, e)
} else if !cpt.IsStarted() {
_, _ = fmt.Fprintln(err, fmt.Errorf("component is not started"))
}
}
}
}))
return res
}

View File

@@ -60,8 +60,9 @@ const (
MinPkgSMTPConfig = 3050
MinPkgStatic = 3100
MinPkgStatus = 3200
MinPkgVersion = 3300
MinPkgViper = 3400
MinPkgSocket = 3300
MinPkgVersion = 3400
MinPkgViper = 3500
MinAvailable = 4000

66
go.mod
View File

@@ -3,11 +3,11 @@ module github.com/nabbar/golib
go 1.20
require (
github.com/aws/aws-sdk-go-v2 v1.18.1
github.com/aws/aws-sdk-go-v2/config v1.18.27
github.com/aws/aws-sdk-go-v2/credentials v1.13.26
github.com/aws/aws-sdk-go-v2/service/iam v1.21.0
github.com/aws/aws-sdk-go-v2/service/s3 v1.36.0
github.com/aws/aws-sdk-go-v2 v1.19.0
github.com/aws/aws-sdk-go-v2/config v1.18.28
github.com/aws/aws-sdk-go-v2/credentials v1.13.27
github.com/aws/aws-sdk-go-v2/service/iam v1.21.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0
github.com/bits-and-blooms/bitset v1.8.0
github.com/c-bata/go-prompt v0.2.6
github.com/fatih/color v1.15.0
@@ -28,11 +28,11 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/nats-io/jwt/v2 v2.4.1
github.com/nats-io/nats-server/v2 v2.9.19
github.com/nats-io/nats.go v1.27.1
github.com/nats-io/nats-server/v2 v2.9.20
github.com/nats-io/nats.go v1.28.0
github.com/nutsdb/nutsdb v0.12.3
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.8
github.com/onsi/gomega v1.27.9
github.com/pelletier/go-toml v1.9.5
github.com/prometheus/client_golang v1.16.0
github.com/shirou/gopsutil v3.21.11+incompatible
@@ -42,15 +42,15 @@ require (
github.com/spf13/viper v1.16.0
github.com/ugorji/go/codec v1.2.11
github.com/vbauerster/mpb/v5 v5.4.0
github.com/xanzy/go-gitlab v0.86.0
github.com/xanzy/go-gitlab v0.88.0
github.com/xhit/go-simple-mail v2.2.2+incompatible
github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/net v0.11.0
golang.org/x/oauth2 v0.9.0
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0
golang.org/x/net v0.12.0
golang.org/x/oauth2 v0.10.0
golang.org/x/sync v0.3.0
golang.org/x/sys v0.10.0
golang.org/x/term v0.9.0
golang.org/x/term v0.10.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/clickhouse v0.5.1
gorm.io/driver/mysql v1.5.1
@@ -62,8 +62,8 @@ require (
require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/ClickHouse/ch-go v0.57.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.10.1 // indirect
github.com/ClickHouse/ch-go v0.58.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.11.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
@@ -75,18 +75,18 @@ require (
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.26 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.27 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.29 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.30 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bwmarrin/snowflake v0.3.0 // indirect
@@ -118,7 +118,7 @@ require (
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -135,7 +135,7 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.4.1 // indirect
github.com/jackc/pgx/v5 v5.4.2 // indirect
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
@@ -153,7 +153,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/mattn/go-tty v0.0.5 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/microsoft/go-mssqldb v1.3.0 // indirect
github.com/microsoft/go-mssqldb v1.4.0 // indirect
github.com/miekg/dns v1.1.55 // indirect
github.com/minio/highwayhash v1.0.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
@@ -163,8 +163,8 @@ require (
github.com/nats-io/nkeys v0.4.4 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/paulmach/orb v0.9.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/paulmach/orb v0.10.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/term v1.2.0-beta.2 // indirect
@@ -193,11 +193,11 @@ require (
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
golang.org/x/arch v0.4.0 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.10.0 // indirect
golang.org/x/tools v0.11.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect

View File

@@ -33,12 +33,10 @@ import (
"net/url"
"time"
libptc "github.com/nabbar/golib/network/protocol"
"golang.org/x/net/http2"
libtls "github.com/nabbar/golib/certificates"
liberr "github.com/nabbar/golib/errors"
libptc "github.com/nabbar/golib/network/protocol"
"golang.org/x/net/http2"
)
const (
@@ -53,78 +51,57 @@ const (
type FctHttpClient func() *http.Client
func GetClient(serverName string) *http.Client {
c, e := GetClientTimeout(serverName, true, 0)
if e != nil {
c, _ = GetClientTimeout(serverName, false, 0)
}
return c
}
func GetClientError(serverName string) (*http.Client, liberr.Error) {
return GetClientTimeout(serverName, true, 0)
}
func GetClientTimeout(serverName string, http2Tr bool, GlobalTimeout time.Duration) (*http.Client, liberr.Error) {
dl := &net.Dialer{}
tr := &http.Transport{
func GetTransport(DisableKeepAlive, DisableCompression, ForceHTTP2 bool) *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dl.DialContext,
DisableCompression: true,
//nolint #staticcheck
TLSClientConfig: libtls.GetTLSConfig(serverName),
DialContext: nil,
DialTLSContext: nil,
TLSClientConfig: nil,
DisableKeepAlives: DisableKeepAlive,
DisableCompression: DisableCompression,
ForceAttemptHTTP2: ForceHTTP2,
}
return getclient(tr, http2Tr, GlobalTimeout)
}
func GetClientCustom(tr *http.Transport, http2Tr bool, GlobalTimeout time.Duration) (*http.Client, liberr.Error) {
return getclient(tr, http2Tr, GlobalTimeout)
func SetTransportTLS(tr *http.Transport, tls libtls.TLSConfig, servername string) {
tr.TLSClientConfig = tls.TlsConfig(servername)
}
func GetClientTls(serverName string, tls libtls.TLSConfig, http2Tr bool, GlobalTimeout time.Duration) (*http.Client, liberr.Error) {
dl := &net.Dialer{}
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dl.DialContext,
DisableCompression: true,
//nolint #staticcheck
TLSClientConfig: tls.TlsConfig(serverName),
}
return getclient(tr, http2Tr, GlobalTimeout)
func SetTransportProxy(tr *http.Transport, proxyUrl *url.URL) {
tr.Proxy = http.ProxyURL(proxyUrl)
}
func GetClientTlsForceIp(netw libptc.NetworkProtocol, ip string, serverName string, tls libtls.TLSConfig, http2Tr bool, GlobalTimeout time.Duration) (*http.Client, liberr.Error) {
u := &url.URL{
Host: ip,
}
func SetTransportDial(tr *http.Transport, forceIp bool, netw libptc.NetworkProtocol, ip, local string) {
var (
fctDial func(ctx context.Context, network, address string) (net.Conn, error)
)
fctDial := func(ctx context.Context, network, address string) (net.Conn, error) {
dl := &net.Dialer{
LocalAddr: &net.TCPAddr{
IP: net.ParseIP(u.Hostname()),
},
if forceIp && len(local) > 0 {
u := &url.URL{
Host: local,
}
return dl.DialContext(ctx, netw.Code(), ip)
fctDial = func(ctx context.Context, network, address string) (net.Conn, error) {
dl := &net.Dialer{
LocalAddr: &net.TCPAddr{
IP: net.ParseIP(u.Hostname()),
},
}
return dl.DialContext(ctx, netw.Code(), ip)
}
} else if forceIp {
fctDial = func(ctx context.Context, network, address string) (net.Conn, error) {
dl := &net.Dialer{}
return dl.DialContext(ctx, netw.Code(), ip)
}
} else {
dl := &net.Dialer{}
fctDial = dl.DialContext
}
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: fctDial,
DisableCompression: true,
//nolint #staticcheck
TLSClientConfig: tls.TlsConfig(serverName),
}
return getclient(tr, http2Tr, GlobalTimeout)
tr.DialContext = fctDial
}
func getclient(tr *http.Transport, http2Tr bool, GlobalTimeout time.Duration) (*http.Client, liberr.Error) {
func GetClient(tr *http.Transport, http2Tr bool, GlobalTimeout time.Duration) (*http.Client, liberr.Error) {
if http2Tr {
if e := http2.ConfigureTransport(tr); e != nil {
return nil, ErrorClientTransportHttp2.ErrorParent(e)

View File

@@ -29,6 +29,8 @@ import (
"io"
"net/http"
libptc "github.com/nabbar/golib/network/protocol"
libtls "github.com/nabbar/golib/certificates"
"github.com/nabbar/golib/httpcli"
. "github.com/onsi/ginkgo/v2"
@@ -59,7 +61,7 @@ var _ = Describe("HttpCli", func() {
},
ForceIP: httpcli.OptionForceIP{
Enable: true,
Net: "tcp",
Net: libptc.NetworkTCP,
IP: "127.0.0.1:8080",
},
}

View File

@@ -31,23 +31,22 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
libptc "github.com/nabbar/golib/network/protocol"
libval "github.com/go-playground/validator/v10"
libtls "github.com/nabbar/golib/certificates"
cmptls "github.com/nabbar/golib/config/components/tls"
cfgcst "github.com/nabbar/golib/config/const"
libval "github.com/go-playground/validator/v10"
libtls "github.com/nabbar/golib/certificates"
liberr "github.com/nabbar/golib/errors"
libptc "github.com/nabbar/golib/network/protocol"
)
type OptionForceIP struct {
Enable bool `json:"enable" yaml:"enable" toml:"enable" mapstructure:"enable"`
Net string `json:"net,omitempty" yaml:"net,omitempty" toml:"net,omitempty" mapstructure:"net,omitempty"`
IP string `json:"ip,omitempty" yaml:"ip,omitempty" toml:"ip,omitempty" mapstructure:"ip,omitempty"`
Enable bool `json:"enable" yaml:"enable" toml:"enable" mapstructure:"enable"`
Net libptc.NetworkProtocol `json:"net,omitempty" yaml:"net,omitempty" toml:"net,omitempty" mapstructure:"net,omitempty"`
IP string `json:"ip,omitempty" yaml:"ip,omitempty" toml:"ip,omitempty" mapstructure:"ip,omitempty"`
Local string `json:"local,omitempty" yaml:"local,omitempty" toml:"local,omitempty" mapstructure:"local,omitempty"`
}
type OptionTLS struct {
@@ -55,11 +54,19 @@ type OptionTLS struct {
Config libtls.Config `json:"tls" yaml:"tls" toml:"tls" mapstructure:"tls"`
}
type OptionProxy struct {
Enable bool `json:"enable" yaml:"enable" toml:"enable" mapstructure:"enable"`
Endpoint *url.URL `json:"endpoint" yaml:"endpoint" toml:"endpoint" mapstructure:"endpoint"`
Username string `json:"username" yaml:"username" toml:"username" mapstructure:"username"`
Password string `json:"password" yaml:"password" toml:"password" mapstructure:"password"`
}
type Options struct {
Timeout time.Duration `json:"timeout" yaml:"timeout" toml:"timeout" mapstructure:"timeout"`
Http2 bool `json:"http2" yaml:"http2" toml:"http2" mapstructure:"http2"`
TLS OptionTLS `json:"tls" yaml:"tls" toml:"tls" mapstructure:"tls"`
ForceIP OptionForceIP `json:"force_ip" yaml:"force_ip" toml:"force_ip" mapstructure:"force_ip"`
Proxy OptionProxy `json:"proxy" yaml:"proxy" toml:"proxy" mapstructure:"proxy"`
}
func DefaultConfig(indent string) []byte {
@@ -72,7 +79,14 @@ func DefaultConfig(indent string) []byte {
"force_ip": {
"enable": false,
"net":"tcp",
"ip":"127.0.0.1:8080"
"ip":"127.0.0.1:8080",
"local":"127.0.0.1"
},
"proxy": {
"enable": false,
"endpoint":"http://example.com",
"username":"example",
"password":"example"
}
}`)
)
@@ -113,11 +127,47 @@ func (o Options) GetClient(def libtls.TLSConfig, servername string) (*http.Clien
tls = t
}
if o.ForceIP.Enable {
return GetClientTlsForceIp(libptc.Parse(o.ForceIP.Net), o.ForceIP.IP, servername, tls, o.Http2, o.Timeout)
} else {
return GetClientTls(servername, tls, o.Http2, o.Timeout)
var tr *http.Transport
tr = GetTransport(false, false, o.Http2)
SetTransportTLS(tr, tls, "")
SetTransportDial(tr, o.ForceIP.Enable, o.ForceIP.Net, o.ForceIP.IP, o.ForceIP.Local)
if o.Proxy.Enable && o.Proxy.Endpoint != nil {
var edp *url.URL
edp = &url.URL{
Scheme: o.Proxy.Endpoint.Scheme,
Opaque: o.Proxy.Endpoint.Opaque,
User: nil,
Host: o.Proxy.Endpoint.Host,
Path: o.Proxy.Endpoint.Path,
RawPath: o.Proxy.Endpoint.RawPath,
OmitHost: o.Proxy.Endpoint.OmitHost,
ForceQuery: o.Proxy.Endpoint.ForceQuery,
RawQuery: o.Proxy.Endpoint.RawQuery,
Fragment: o.Proxy.Endpoint.Fragment,
RawFragment: o.Proxy.Endpoint.RawFragment,
}
if len(o.Proxy.Password) > 0 {
edp.User = url.UserPassword(o.Proxy.Username, o.Proxy.Password)
} else if len(o.Proxy.Username) > 0 {
edp.User = url.User(o.Proxy.Username)
} else if o.Proxy.Endpoint.User != nil {
if p, k := o.Proxy.Endpoint.User.Password(); k {
edp.User = url.UserPassword(o.Proxy.Endpoint.User.Username(), p)
} else {
edp.User = url.User(o.Proxy.Endpoint.User.Username())
}
}
if edp != nil && len(edp.String()) > 0 {
SetTransportProxy(tr, edp)
}
}
return GetClient(tr, o.Http2, o.Timeout)
}
func (o Options) _GetTLS(def libtls.TLSConfig) (libtls.TLSConfig, liberr.Error) {

View File

@@ -47,7 +47,7 @@ func (o *hkf) Write(p []byte) (n int, err error) {
}
func (o *hkf) Close() error {
fmt.Printf("closing hook for log file '%s'\n", o.getFilepath())
//fmt.Printf("closing hook for log file '%s'\n", o.getFilepath())
o.d.Store(closeByte)
time.Sleep(10 * time.Millisecond)

View File

@@ -121,7 +121,7 @@ func (o *hkf) Run(ctx context.Context) {
}()
o.prepareChan()
fmt.Printf("starting hook for log file '%s'\n", o.getFilepath())
//fmt.Printf("starting hook for log file '%s'\n", o.getFilepath())
for {
select {

View File

@@ -61,7 +61,7 @@ func (o *hks) WriteSev(s SyslogSeverity, p []byte) (n int, err error) {
}
func (o *hks) Close() error {
fmt.Printf("closing hook for log syslog '%s'\n", o.getSyslogInfo())
//fmt.Printf("closing hook for log syslog '%s'\n", o.getSyslogInfo())
o.d.Store(closeByte)
time.Sleep(10 * time.Millisecond)

View File

@@ -62,7 +62,7 @@ func (o *hks) Run(ctx context.Context) {
}
o.prepareChan()
fmt.Printf("starting hook for log syslog '%s'\n", o.getSyslogInfo())
//fmt.Printf("starting hook for log syslog '%s'\n", o.getSyslogInfo())
for {
select {

View File

@@ -37,34 +37,66 @@ import (
)
func (o *logger) Debug(message string, data interface{}, args ...interface{}) {
if o == nil {
return
}
o.newEntry(loglvl.DebugLevel, fmt.Sprintf(message, args...), nil, nil, data).Log()
}
func (o *logger) Info(message string, data interface{}, args ...interface{}) {
if o == nil {
return
}
o.newEntry(loglvl.InfoLevel, fmt.Sprintf(message, args...), nil, nil, data).Log()
}
func (o *logger) Warning(message string, data interface{}, args ...interface{}) {
if o == nil {
return
}
o.newEntry(loglvl.WarnLevel, fmt.Sprintf(message, args...), nil, nil, data).Log()
}
func (o *logger) Error(message string, data interface{}, args ...interface{}) {
if o == nil {
return
}
o.newEntry(loglvl.ErrorLevel, fmt.Sprintf(message, args...), nil, nil, data).Log()
}
func (o *logger) Fatal(message string, data interface{}, args ...interface{}) {
if o == nil {
return
}
o.newEntry(loglvl.FatalLevel, fmt.Sprintf(message, args...), nil, nil, data).Log()
}
func (o *logger) Panic(message string, data interface{}, args ...interface{}) {
if o == nil {
return
}
o.newEntry(loglvl.PanicLevel, fmt.Sprintf(message, args...), nil, nil, data).Log()
}
func (o *logger) LogDetails(lvl loglvl.Level, message string, data interface{}, err []error, fields logfld.Fields, args ...interface{}) {
if o == nil {
return
}
o.newEntry(lvl, fmt.Sprintf(message, args...), err, fields, data).Log()
}
func (o *logger) CheckError(lvlKO, lvlOK loglvl.Level, message string, err ...error) bool {
if o == nil {
return false
}
ent := o.newEntry(lvlKO, message, err, nil, nil)
return ent.Check(lvlOK)
}
@@ -79,21 +111,37 @@ func (o *logger) Access(remoteAddr, remoteUser string, localtime time.Time, late
}
func (o *logger) newEntry(lvl loglvl.Level, message string, err []error, fields logfld.Fields, data interface{}) logent.Entry {
if o == nil {
return logent.New(loglvl.NilLevel)
}
var (
fct = o.getLogrus
ent = logent.New(lvl)
frm = o.getCaller()
stk = o.getStack()
fld = o.GetFields()
)
if o == nil {
return logent.New(loglvl.NilLevel)
} else if fld != nil {
ent.FieldSet(fld.FieldsClone(nil))
}
ent.ErrorSet(err)
ent.FieldSet(o.GetFields().FieldsClone(nil))
ent.DataSet(data)
ent.SetLogger(o.getLogrus)
ent.SetEntryContext(time.Now(), o.getStack(), frm.Function, frm.File, uint64(frm.Line), message)
ent.SetLogger(fct)
ent.SetEntryContext(time.Now(), stk, frm.Function, frm.File, uint64(frm.Line), message)
ent.FieldMerge(fields)
return ent
}
func (o *logger) newEntryClean(message string) logent.Entry {
if o == nil {
return logent.New(loglvl.NilLevel)
}
return o.newEntry(loglvl.InfoLevel, message, nil, nil, nil).SetMessageOnly(true)
}

View File

@@ -32,9 +32,8 @@ import (
"strings"
"time"
moninf "github.com/nabbar/golib/monitor/types"
monsts "github.com/nabbar/golib/monitor/status"
moninf "github.com/nabbar/golib/monitor/types"
)
const (

View File

@@ -30,11 +30,9 @@ import (
"context"
"time"
"golang.org/x/exp/slices"
libprm "github.com/nabbar/golib/prometheus"
monsts "github.com/nabbar/golib/monitor/status"
libprm "github.com/nabbar/golib/prometheus"
"golang.org/x/exp/slices"
)
func (o *mon) RegisterMetricsName(names ...string) {

View File

@@ -29,7 +29,7 @@ package monitor
import (
"context"
"github.com/nabbar/golib/monitor/types"
montps "github.com/nabbar/golib/monitor/types"
)
type fctMiddleWare func(m middleWare) error
@@ -49,7 +49,7 @@ type mdl struct {
mdl []fctMiddleWare
}
func newMiddleware(cfg *runCfg, fct types.HealthCheck) middleWare {
func newMiddleware(cfg *runCfg, fct montps.HealthCheck) middleWare {
o := &mdl{
ctx: nil,
cfg: cfg,

View File

@@ -31,13 +31,11 @@ import (
"sync"
"time"
liblog "github.com/nabbar/golib/logger"
libsrv "github.com/nabbar/golib/server"
libctx "github.com/nabbar/golib/context"
liblog "github.com/nabbar/golib/logger"
montps "github.com/nabbar/golib/monitor/types"
libprm "github.com/nabbar/golib/prometheus"
libsrv "github.com/nabbar/golib/server"
)
type Pool interface {

218
monitor/pool/shell.go 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 pool
import (
"context"
"fmt"
"io"
monsts "github.com/nabbar/golib/monitor/status"
shlcmd "github.com/nabbar/golib/shell/command"
)
func ShellCommandInfo() []shlcmd.CommandInfo {
var res = make([]shlcmd.CommandInfo, 0)
res = append(res, shlcmd.Info("list", "Print the monitors' List"))
res = append(res, shlcmd.Info("info", "Print information about monitors (leave args empty to print info for all monitors)"))
res = append(res, shlcmd.Info("start", "Starting monitor (leave args empty to start all monitors)"))
res = append(res, shlcmd.Info("stop", "Stopping monitor (leave args empty to stop all monitors)"))
res = append(res, shlcmd.Info("restart", "Restarting monitor (leave args empty to restart all monitors)"))
res = append(res, shlcmd.Info("status", "Print status & message for monitor (leave args empty to print status of all monitors)"))
return res
}
func (p *pool) GetShellCommand(ctx context.Context) []shlcmd.Command {
var res = make([]shlcmd.Command, 0)
res = append(res, shlcmd.New("list", "Print the monitors' List", func(buf io.Writer, err io.Writer, args []string) {
var list = p.MonitorList()
for i := 0; i < len(list); i++ {
_, _ = fmt.Fprintln(buf, list[i])
}
}))
res = append(res, shlcmd.New("info", "Print information about monitors (leave args empty to print info for all monitors)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = p.MonitorList()
}
for i := 0; i < len(list); i++ {
if len(list[i]) < 1 {
continue
}
m := p.MonitorGet(list[i])
if m == nil {
continue
}
inf := m.InfoGet()
_, _ = fmt.Fprintln(buf, inf.Name())
for k, v := range inf.Info() {
_, _ = fmt.Fprintln(buf, fmt.Sprintf("\t%s: %s", k, v))
}
_, _ = fmt.Fprintln(buf, "")
}
}))
res = append(res, shlcmd.New("start", "Starting monitor (leave args empty to start all monitors)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = p.MonitorList()
}
for i := 0; i < len(list); i++ {
if len(list[i]) < 1 {
continue
}
m := p.MonitorGet(list[i])
if m == nil {
continue
}
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Starting monitor '%s'", list[i]))
if e := m.Start(ctx); e != nil {
_, _ = fmt.Fprintln(err, e)
}
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Updating monitor '%s' on pool", list[i]))
if e := p.MonitorSet(m); e != nil {
_, _ = fmt.Fprintln(err, e)
}
}
}))
res = append(res, shlcmd.New("stop", "Stopping monitor (leave args empty to stop all monitors)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = p.MonitorList()
}
for i := 0; i < len(list); i++ {
if len(list[i]) < 1 {
continue
}
m := p.MonitorGet(list[i])
if m == nil {
continue
}
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Stopping monitor '%s'", list[i]))
if e := m.Stop(ctx); e != nil {
_, _ = fmt.Fprintln(err, e)
}
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Updating monitor '%s' on pool", list[i]))
if e := p.MonitorSet(m); e != nil {
_, _ = fmt.Fprintln(err, e)
}
}
}))
res = append(res, shlcmd.New("restart", "Restarting monitor (leave args empty to restart all monitors)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = p.MonitorList()
}
for i := 0; i < len(list); i++ {
if len(list[i]) < 1 {
continue
}
m := p.MonitorGet(list[i])
if m == nil {
continue
}
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Stopping monitor '%s'", list[i]))
if e := m.Stop(ctx); e != nil {
_, _ = fmt.Fprintln(err, e)
}
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Starting monitor '%s'", list[i]))
if e := m.Start(ctx); e != nil {
_, _ = fmt.Fprintln(err, e)
}
_, _ = fmt.Fprintln(buf, fmt.Sprintf("Updating monitor '%s' on pool", list[i]))
if e := p.MonitorSet(m); e != nil {
_, _ = fmt.Fprintln(err, e)
}
}
}))
res = append(res, shlcmd.New("status", "Print status & message for monitor (leave args empty to print status of all monitors)", func(buf io.Writer, err io.Writer, args []string) {
var list []string
if len(args) > 0 {
list = args
} else {
list = p.MonitorList()
}
for i := 0; i < len(list); i++ {
if len(list[i]) < 1 {
continue
}
m := p.MonitorGet(list[i])
if m == nil {
continue
}
s := m.Status()
if s == monsts.OK {
_, _ = fmt.Fprintln(buf, fmt.Sprintf("%s - %s", s.String(), list[i]))
} else {
_, _ = fmt.Fprintln(err, fmt.Sprintf("%s - %s: %s", s.String(), list[i], m.Message()))
}
}
}))
return res
}

View File

@@ -32,11 +32,9 @@ import (
"encoding/json"
"time"
liblog "github.com/nabbar/golib/logger"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
monsts "github.com/nabbar/golib/monitor/status"
libprm "github.com/nabbar/golib/prometheus"
libsrv "github.com/nabbar/golib/server"

View File

@@ -27,20 +27,16 @@
package types
import (
"context"
"encoding"
"encoding/json"
shlcmd "github.com/nabbar/golib/shell/command"
)
type FuncPool func() Pool
type PoolStatus interface {
encoding.TextMarshaler
json.Marshaler
}
type Pool interface {
PoolStatus
type PoolManage interface {
MonitorAdd(mon Monitor) error
MonitorGet(name string) Monitor
MonitorSet(mon Monitor) error
@@ -48,3 +44,18 @@ type Pool interface {
MonitorList() []string
MonitorWalk(fct func(name string, val Monitor) bool, validName ...string)
}
type PoolStatus interface {
encoding.TextMarshaler
json.Marshaler
PoolManage
}
type PoolShell interface {
GetShellCommand(ctx context.Context) []shlcmd.Command
}
type Pool interface {
PoolStatus
PoolShell
}

View File

@@ -43,6 +43,9 @@ const (
NetworkUDP
NetworkUDP4
NetworkUDP6
NetworkIP
NetworkIP4
NetworkIP6
)
func Parse(str string) NetworkProtocol {
@@ -66,7 +69,7 @@ func ParseBytes(p []byte) NetworkProtocol {
return Parse(string(p))
}
func SizeFromInt64(val int64) NetworkProtocol {
func ParseInt64(val int64) NetworkProtocol {
if val > int64(math.MaxUint8) {
return NetworkProtocol(math.MaxUint8)
}

View File

@@ -27,7 +27,12 @@
package protocol
import "strings"
import (
"reflect"
"strings"
libmap "github.com/mitchellh/mapstructure"
)
func (n NetworkProtocol) String() string {
switch n {
@@ -45,6 +50,12 @@ func (n NetworkProtocol) String() string {
return "udp4"
case NetworkUDP6:
return "udp6"
case NetworkIP:
return "ip"
case NetworkIP4:
return "ip4"
case NetworkIP6:
return "ip6"
default:
return ""
}
@@ -53,3 +64,32 @@ func (n NetworkProtocol) String() string {
func (n NetworkProtocol) Code() string {
return strings.ToLower(n.String())
}
func ViperDecoderHook() libmap.DecodeHookFuncType {
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
var (
z = NetworkProtocol(0)
t string
k bool
)
// Check if the data type matches the expected one
if from.Kind() != reflect.String {
return data, nil
} else if t, k = data.(string); !k {
return data, nil
}
// Check if the target type matches the expected one
if to != reflect.TypeOf(z) {
return data, nil
}
// Format/decode/parse the data and return the new value
if e := z.unmarshall([]byte(t)); e != nil {
return nil, e
} else {
return z, nil
}
}
}

View File

@@ -40,7 +40,7 @@ import (
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
montps "github.com/nabbar/golib/monitor/types"
libsh "github.com/nabbar/golib/shell"
shlcmd "github.com/nabbar/golib/shell/command"
libver "github.com/nabbar/golib/version"
)
@@ -66,7 +66,7 @@ type NutsDB interface {
Cluster() libclu.Cluster
Client(ctx context.Context, tickSync time.Duration) Client
ShellCommand(ctx func() context.Context, tickSync time.Duration) []libsh.Command
ShellCommand(ctx func() context.Context, tickSync time.Duration) []shlcmd.Command
}
func New(c Config) NutsDB {

View File

@@ -40,7 +40,7 @@ import (
libclu "github.com/nabbar/golib/cluster"
liberr "github.com/nabbar/golib/errors"
liblog "github.com/nabbar/golib/logger"
libsh "github.com/nabbar/golib/shell"
shlcmd "github.com/nabbar/golib/shell/command"
)
type ndb struct {
@@ -265,9 +265,9 @@ func (n *ndb) Client(ctx context.Context, tickSync time.Duration) Client {
}
}
func (n *ndb) ShellCommand(ctx func() context.Context, tickSync time.Duration) []libsh.Command {
func (n *ndb) ShellCommand(ctx func() context.Context, tickSync time.Duration) []shlcmd.Command {
var (
res = make([]libsh.Command, 0)
res = make([]shlcmd.Command, 0)
cli func() Client
)

View File

@@ -35,7 +35,7 @@ import (
"fmt"
"io"
libsh "github.com/nabbar/golib/shell"
shlcmd "github.com/nabbar/golib/shell/command"
"github.com/nutsdb/nutsdb"
"github.com/nutsdb/nutsdb/ds/zset"
)
@@ -45,7 +45,7 @@ type shellCommand struct {
c func() Client
}
func newShellCommand(code CmdCode, cli func() Client) libsh.Command {
func newShellCommand(code CmdCode, cli func() Client) shlcmd.Command {
if code == CmdUnknown {
return nil
}

View File

@@ -0,0 +1,58 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2021 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 command
import "io"
type FuncRun func(buf io.Writer, err io.Writer, args []string)
type CommandInfo interface {
Name() string
Describe() string
}
type Command interface {
CommandInfo
Run(buf io.Writer, err io.Writer, args []string)
}
func New(name, desc string, fct FuncRun) Command {
return &model{
n: name,
d: desc,
r: fct,
}
}
func Info(name, desc string) CommandInfo {
return &model{
n: name,
d: desc,
r: nil,
}
}

62
shell/command/model.go Normal file
View File

@@ -0,0 +1,62 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2021 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 command
import (
"io"
)
type model struct {
n string
d string
r FuncRun
}
func (o *model) Name() string {
if o == nil {
return ""
}
return o.n
}
func (o *model) Describe() string {
if o == nil {
return ""
}
return o.d
}
func (o *model) Run(buf io.Writer, err io.Writer, args []string) {
if o == nil || o.r == nil {
return
}
o.r(buf, err, args)
}

View File

@@ -33,12 +33,13 @@ import (
"os"
"strings"
"github.com/c-bata/go-prompt"
libshl "github.com/c-bata/go-prompt"
liberr "github.com/nabbar/golib/errors"
shlcmd "github.com/nabbar/golib/shell/command"
)
func (s *shell) RunPrompt(out, err io.Writer, opt ...prompt.Option) {
p := prompt.New(
func (s *shell) RunPrompt(out, err io.Writer, opt ...libshl.Option) {
p := libshl.New(
func(inputLine string) {
if out == nil {
out = os.Stdout
@@ -59,11 +60,11 @@ func (s *shell) RunPrompt(out, err io.Writer, opt ...prompt.Option) {
s.Run(out, err, strings.Fields(inputLine))
},
func(document prompt.Document) []prompt.Suggest {
var res = make([]prompt.Suggest, 0)
func(document libshl.Document) []libshl.Suggest {
var res = make([]libshl.Suggest, 0)
_ = s.Walk(func(name string, item Command) (Command, liberr.Error) {
res = append(res, prompt.Suggest{
_ = s.Walk(func(name string, item shlcmd.Command) (shlcmd.Command, liberr.Error) {
res = append(res, libshl.Suggest{
Text: name,
Description: item.Describe(),
})

View File

@@ -30,30 +30,24 @@ package shell
import (
"io"
"github.com/c-bata/go-prompt"
libshl "github.com/c-bata/go-prompt"
liberr "github.com/nabbar/golib/errors"
shlcmd "github.com/nabbar/golib/shell/command"
)
type Command interface {
Name() string
Describe() string
Run(buf io.Writer, err io.Writer, args []string)
}
type Shell interface {
Run(buf io.Writer, err io.Writer, args []string)
Add(prefix string, cmd ...Command)
Get(cmd string) []Command
Add(prefix string, cmd ...shlcmd.Command)
Get(cmd string) []shlcmd.Command
Desc(cmd string) map[string]string
Walk(fct func(name string, item Command) (Command, liberr.Error)) liberr.Error
Walk(fct func(name string, item shlcmd.Command) (shlcmd.Command, liberr.Error)) liberr.Error
//go prompt
RunPrompt(out, err io.Writer, opt ...prompt.Option)
RunPrompt(out, err io.Writer, opt ...libshl.Option)
}
func New() Shell {
return &shell{
c: make(map[string]Command),
c: make(map[string]shlcmd.Command),
}
}

View File

@@ -32,10 +32,11 @@ import (
"io"
liberr "github.com/nabbar/golib/errors"
shlcmd "github.com/nabbar/golib/shell/command"
)
type shell struct {
c map[string]Command
c map[string]shlcmd.Command
}
func (s *shell) Run(buf io.Writer, err io.Writer, args []string) {
@@ -55,7 +56,7 @@ func (s *shell) Run(buf io.Writer, err io.Writer, args []string) {
}
}
func (s *shell) Walk(fct func(name string, item Command) (Command, liberr.Error)) liberr.Error {
func (s *shell) Walk(fct func(name string, item shlcmd.Command) (shlcmd.Command, liberr.Error)) liberr.Error {
if fct == nil {
return nil
}
@@ -77,9 +78,9 @@ func (s *shell) Walk(fct func(name string, item Command) (Command, liberr.Error)
return nil
}
func (s *shell) Add(prefix string, cmd ...Command) {
func (s *shell) Add(prefix string, cmd ...shlcmd.Command) {
if len(s.c) == 0 {
s.c = make(map[string]Command)
s.c = make(map[string]shlcmd.Command)
}
for i := 0; i < len(cmd); i++ {
@@ -98,10 +99,10 @@ func (s *shell) Add(prefix string, cmd ...Command) {
}
}
func (s *shell) Get(cmd string) []Command {
var res = make([]Command, 0)
func (s *shell) Get(cmd string) []shlcmd.Command {
var res = make([]shlcmd.Command, 0)
_ = s.Walk(func(name string, item Command) (Command, liberr.Error) {
_ = s.Walk(func(name string, item shlcmd.Command) (shlcmd.Command, liberr.Error) {
if len(cmd) == 0 || name == cmd {
res = append(res, item)
}
@@ -115,7 +116,7 @@ func (s *shell) Get(cmd string) []Command {
func (s *shell) Desc(cmd string) map[string]string {
var res = make(map[string]string)
_ = s.Walk(func(name string, item Command) (Command, liberr.Error) {
_ = s.Walk(func(name string, item shlcmd.Command) (shlcmd.Command, liberr.Error) {
if len(cmd) == 0 || name == cmd {
res[name] = item.Describe()
}

27
socket/client/ignore.go 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 client

View File

@@ -0,0 +1,55 @@
//go:build linux
// +build linux
/*
* 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 client
import (
"context"
"io"
"sync/atomic"
libsck "github.com/nabbar/golib/socket"
)
type Client interface {
RegisterFuncError(f libsck.FuncError)
Connection(ctx context.Context, request io.Reader) (io.Reader, error)
}
func New(unixfile string) Client {
u := new(atomic.Value)
u.Store(unixfile)
return &clt{
u: u,
f: new(atomic.Value),
tr: new(atomic.Value),
tw: new(atomic.Value),
}
}

126
socket/client/model.go Normal file
View File

@@ -0,0 +1,126 @@
//go:build linux
// +build linux
/*
* 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 client
import (
"bytes"
"context"
"fmt"
"io"
"net"
"os"
"sync/atomic"
libsck "github.com/nabbar/golib/socket"
)
type clt struct {
u *atomic.Value // unixfile
f *atomic.Value // function error
tr *atomic.Value // connection read timeout
tw *atomic.Value // connection write timeout
}
func (o *clt) RegisterFuncError(f libsck.FuncError) {
if o == nil {
return
}
o.f.Store(f)
}
func (o *clt) fctError(e error) {
if o == nil {
return
}
v := o.f.Load()
if v != nil {
v.(libsck.FuncError)(e)
}
}
func (o *clt) dial(ctx context.Context) (net.Conn, error) {
if o == nil {
return nil, fmt.Errorf("invalid instance")
}
v := o.u.Load()
if v == nil {
return nil, fmt.Errorf("invalid unix file")
} else if _, e := os.Stat(v.(string)); e != nil {
return nil, e
} else {
d := net.Dialer{}
return d.DialContext(ctx, "unix", v.(string))
}
}
func (o *clt) Connection(ctx context.Context, request io.Reader) (io.Reader, error) {
if o == nil {
return nil, fmt.Errorf("invalid instance")
}
var (
e error
cnn net.Conn
)
if cnn, e = o.dial(ctx); e != nil {
o.fctError(e)
return nil, e
}
defer cnn.Close()
if request != nil {
if _, e = io.Copy(cnn, request); e != nil {
o.fctError(e)
return nil, e
}
}
if e = cnn.(*net.UnixConn).CloseWrite(); e != nil {
o.fctError(e)
return nil, e
}
var buf = bytes.NewBuffer(make([]byte, 0, 32*1024))
if _, e = io.Copy(buf, cnn); e != nil {
o.fctError(e)
return nil, e
}
_ = cnn.(*net.UnixConn).CloseRead()
return buf, nil
}

27
socket/ignore.go 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 socket

80
socket/inerface.go Normal file
View File

@@ -0,0 +1,80 @@
//go:build linux
// +build linux
/*
* 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 socket
import (
"context"
"io"
"os"
"sync/atomic"
"time"
)
type FuncError func(e error)
type Handler func(request io.Reader, response io.Writer)
type Server interface {
RegisterFuncError(f FuncError)
SetReadTimeout(d time.Duration)
SetWriteTimeout(d time.Duration)
Listen(ctx context.Context, unixFile string, perm os.FileMode)
Shutdown()
Done() <-chan struct{}
}
func New(h Handler, sizeBuffRead, sizeBuffWrite int32) Server {
c := new(atomic.Value)
c.Store(make(chan []byte))
s := new(atomic.Value)
s.Store(make(chan struct{}))
f := new(atomic.Value)
f.Store(h)
sr := new(atomic.Int32)
sr.Store(sizeBuffRead)
sw := new(atomic.Int32)
sw.Store(sizeBuffWrite)
return &srv{
l: nil,
h: f,
c: c,
s: s,
f: new(atomic.Value),
tr: new(atomic.Value),
tw: new(atomic.Value),
sr: sr,
sw: sw,
}
}

202
socket/listener.go Normal file
View File

@@ -0,0 +1,202 @@
//go:build linux
// +build linux
/*
* 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 socket
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/fs"
"net"
"os"
"path/filepath"
"syscall"
"time"
)
func (o *srv) timeoutRead() time.Time {
v := o.tr.Load()
if v != nil {
return time.Now().Add(v.(time.Duration))
}
return time.Time{}
}
func (o *srv) timeoutWrite() time.Time {
v := o.tw.Load()
if v != nil {
return time.Now().Add(v.(time.Duration))
}
return time.Time{}
}
func (o *srv) buffRead() *bytes.Buffer {
v := o.sr.Load()
if v > 0 {
return bytes.NewBuffer(make([]byte, 0, int(v)))
}
return bytes.NewBuffer(make([]byte, 0, 32*1024))
}
func (o *srv) buffWrite() *bytes.Buffer {
v := o.sw.Load()
if v > 0 {
return bytes.NewBuffer(make([]byte, 0, int(v)))
}
return bytes.NewBuffer(make([]byte, 0, 32*1024))
}
func (o *srv) checkFile(unixFile string) (string, error) {
if len(unixFile) < 1 {
return unixFile, fmt.Errorf("missing socket file path")
} else {
unixFile = filepath.Join(filepath.Dir(unixFile), filepath.Base(unixFile))
}
if _, e := os.Stat(unixFile); e != nil && !errors.Is(e, os.ErrNotExist) {
return unixFile, e
} else if e != nil {
return unixFile, nil
} else if e = os.Remove(unixFile); e != nil {
return unixFile, e
}
return unixFile, nil
}
func (o *srv) Listen(ctx context.Context, unixFile string, perm os.FileMode) {
var (
e error
i fs.FileInfo
l net.Listener
p = syscall.Umask(int(perm))
)
if unixFile, e = o.checkFile(unixFile); e != nil {
o.fctError(e)
return
} else if l, e = net.Listen("unix", unixFile); e != nil {
o.fctError(e)
return
} else if i, e = os.Stat(unixFile); e != nil {
o.fctError(e)
return
}
syscall.Umask(p)
var fctClose = func() {
if l != nil {
o.fctError(l.Close())
}
if i, e = os.Stat(unixFile); e == nil {
o.fctError(os.Remove(unixFile))
}
}
defer fctClose()
if i.Mode() != perm {
if e = os.Chmod(unixFile, perm); e != nil {
o.fctError(e)
}
}
// Accept new connection or stop if context or shutdown trigger
for {
select {
case <-ctx.Done():
return
case <-o.Done():
return
default:
// Accept an incoming connection.
if l == nil {
return
} else if co, ce := l.Accept(); ce != nil {
o.fctError(ce)
} else {
go o.Conn(co)
}
}
}
}
func (o *srv) Conn(conn net.Conn) {
defer conn.Close()
var (
tr = o.timeoutRead()
tw = o.timeoutWrite()
br = o.buffRead()
bw = o.buffWrite()
)
if !tr.IsZero() {
if e := conn.SetReadDeadline(tr); e != nil {
o.fctError(e)
return
}
}
if !tw.IsZero() {
if e := conn.SetReadDeadline(tw); e != nil {
o.fctError(e)
return
}
}
if _, e := io.Copy(br, conn); e != nil {
o.fctError(e)
return
} else if e = conn.(*net.UnixConn).CloseRead(); e != nil {
o.fctError(e)
return
}
if h := o.handler(); h != nil {
h(br, bw)
}
if _, e := io.Copy(conn, bw); e != nil {
o.fctError(e)
return
} else if e = conn.(*net.UnixConn).CloseWrite(); e != nil {
o.fctError(e)
return
}
}

132
socket/model.go Normal file
View File

@@ -0,0 +1,132 @@
//go:build linux
// +build linux
/*
* 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 socket
import (
"net"
"sync/atomic"
"time"
)
const (
defaultTimeoutRead = time.Second
defaultTimeoutWrite = 5 * time.Second
)
var (
closedChanStruct chan struct{}
)
func init() {
closedChanStruct = make(chan struct{})
close(closedChanStruct)
}
type srv struct {
l net.Listener
h *atomic.Value // handler
c *atomic.Value // chan []byte
s *atomic.Value // chan struct{}
f *atomic.Value // function error
tr *atomic.Value // connection read timeout
tw *atomic.Value // connection write timeout
sr *atomic.Int32 // read buffer size
sw *atomic.Int32 // write buffer size
}
func (o *srv) Done() <-chan struct{} {
s := o.s.Load()
if s != nil {
return s.(chan struct{})
}
return closedChanStruct
}
func (o *srv) Shutdown() {
if o == nil {
return
}
s := o.s.Load()
if s != nil {
o.s.Store(nil)
}
}
func (o *srv) RegisterFuncError(f FuncError) {
if o == nil {
return
}
o.f.Store(f)
}
func (o *srv) SetReadTimeout(d time.Duration) {
if o == nil {
return
}
o.tr.Store(d)
}
func (o *srv) SetWriteTimeout(d time.Duration) {
if o == nil {
return
}
o.tw.Store(d)
}
func (o *srv) fctError(e error) {
if o == nil {
return
}
v := o.f.Load()
if v != nil {
v.(FuncError)(e)
}
}
func (o *srv) handler() Handler {
if o == nil {
return nil
}
v := o.h.Load()
if v != nil {
return v.(Handler)
}
return nil
}

View File

@@ -32,7 +32,9 @@ import (
libval "github.com/go-playground/validator/v10"
monsts "github.com/nabbar/golib/monitor/status"
"golang.org/x/exp/slices"
stsctr "github.com/nabbar/golib/status/control"
stslmd "github.com/nabbar/golib/status/listmandatory"
stsmdt "github.com/nabbar/golib/status/mandatory"
)
const (
@@ -42,7 +44,12 @@ const (
type Config struct {
ReturnCode map[monsts.Status]int
MandatoryComponent []string
MandatoryComponent stslmd.ListMandatory
}
type Mandatory struct {
Mode stsctr.Mode
Keys []string
}
func (o Config) Validate() error {
@@ -98,22 +105,37 @@ func (o *sts) cfgGetReturnCode(s monsts.Status) int {
}
}
func (o *sts) cfgIsMandatory(name string) bool {
if i, l := o.x.Load(keyConfigMandatory); !l {
return false
} else if v, k := i.([]string); !k {
return false
} else {
return slices.Contains(v, name)
}
}
func (o *sts) cfgGetMandatory() []string {
func (o *sts) cfgGetMandatory() stslmd.ListMandatory {
if i, l := o.x.Load(keyConfigMandatory); !l {
return nil
} else if v, k := i.([]string); !k {
} else if v, k := i.(stslmd.ListMandatory); !k {
return nil
} else {
return v
}
}
func (o *sts) cfgGetMode(key string) stsctr.Mode {
if l := o.cfgGetMandatory(); len(l) < 1 {
return stsctr.Ignore
} else {
return l.GetMode(key)
}
}
func (o *sts) cfgGetOne(key string) []string {
if l := o.cfgGetMandatory(); len(l) < 1 {
return make([]string, 0)
} else {
var r []string
l.Walk(func(m stsmdt.Mandatory) bool {
if m.KeyHas(key) {
r = m.KeyList()
return false
}
return true
})
return r
}
}

89
status/control/encode.go Normal file
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 control
import (
"fmt"
"gopkg.in/yaml.v3"
)
func (c *Mode) unmarshall(val []byte) error {
*c = ParseBytes(val)
return nil
}
func (c Mode) MarshalJSON() ([]byte, error) {
t := c.String()
b := make([]byte, 0, len(t)+2)
b = append(b, '"')
b = append(b, []byte(t)...)
b = append(b, '"')
return b, nil
}
func (c *Mode) UnmarshalJSON(bytes []byte) error {
return c.unmarshall(bytes)
}
func (c Mode) MarshalYAML() (interface{}, error) {
return []byte(c.String()), nil
}
func (c *Mode) UnmarshalYAML(value *yaml.Node) error {
return c.unmarshall([]byte(value.Value))
}
func (c Mode) MarshalTOML() ([]byte, error) {
return []byte(c.String()), nil
}
func (c *Mode) UnmarshalTOML(i interface{}) error {
if p, k := i.([]byte); k {
return c.unmarshall(p)
}
if p, k := i.(string); k {
return c.unmarshall([]byte(p))
}
return fmt.Errorf("size: value not in valid format")
}
func (c Mode) MarshalText() ([]byte, error) {
return []byte(c.String()), nil
}
func (c *Mode) UnmarshalText(bytes []byte) error {
return c.unmarshall(bytes)
}
func (c Mode) MarshalCBOR() ([]byte, error) {
return []byte(c.String()), nil
}
func (c *Mode) UnmarshalCBOR(bytes []byte) error {
return c.unmarshall(bytes)
}

View File

@@ -0,0 +1,66 @@
/*
* 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 control
import (
"math"
"strings"
)
type Mode uint8
const (
Ignore Mode = iota
Should
Must
One
)
func Parse(s string) Mode {
switch {
case strings.EqualFold(Must.Code(), s):
return Must
case strings.EqualFold(One.Code(), s):
return One
case strings.EqualFold(Should.Code(), s):
return Should
}
return Ignore
}
func ParseBytes(p []byte) Mode {
return Parse(string(p))
}
func ParseInt64(val int64) Mode {
if val > int64(math.MaxUint8) {
return Mode(math.MaxUint8)
}
return Mode(uint8(val))
}

80
status/control/model.go Normal file
View File

@@ -0,0 +1,80 @@
/*
* 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 control
import (
"reflect"
"strings"
libmap "github.com/mitchellh/mapstructure"
)
func (c Mode) String() string {
switch c {
case Must:
return "Must"
case One:
return "One"
case Should:
return "Should"
}
return ""
}
func (c Mode) Code() string {
return strings.ToLower(c.String())
}
func ViperDecoderHook() libmap.DecodeHookFuncType {
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
var (
z = Mode(0)
t string
k bool
)
// Check if the data type matches the expected one
if from.Kind() != reflect.String {
return data, nil
} else if t, k = data.(string); !k {
return data, nil
}
// Check if the target type matches the expected one
if to != reflect.TypeOf(z) {
return data, nil
}
// Format/decode/parse the data and return the new value
if e := z.unmarshall([]byte(t)); e != nil {
return nil, e
} else {
return z, nil
}
}
}

View File

@@ -35,12 +35,10 @@ import (
"strings"
"time"
monpol "github.com/nabbar/golib/monitor/pool"
ginsdk "github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/render"
ginrdr "github.com/gin-gonic/gin/render"
liberr "github.com/nabbar/golib/errors"
monpol "github.com/nabbar/golib/monitor/pool"
monsts "github.com/nabbar/golib/monitor/status"
montps "github.com/nabbar/golib/monitor/types"
)
@@ -88,7 +86,7 @@ func (e *encodeModel) GinRender(c *ginsdk.Context, isText bool, isShort bool) {
}
if isText {
c.Render(e.code, render.Data{
c.Render(e.code, ginrdr.Data{
ContentType: ginsdk.MIMEPlain,
Data: e.Bytes(),
})

View File

@@ -31,15 +31,11 @@ import (
"sync"
"sync/atomic"
liberr "github.com/nabbar/golib/errors"
montps "github.com/nabbar/golib/monitor/types"
libctx "github.com/nabbar/golib/context"
libver "github.com/nabbar/golib/version"
ginsdk "github.com/gin-gonic/gin"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
montps "github.com/nabbar/golib/monitor/types"
libver "github.com/nabbar/golib/version"
)
type Route interface {
@@ -54,7 +50,7 @@ type Info interface {
}
type Pool interface {
montps.Pool
montps.PoolStatus
RegisterPool(fct montps.FuncPool)
}

View File

@@ -0,0 +1,37 @@
/*
* 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 listmandatory
import stsmdt "github.com/nabbar/golib/status/mandatory"
type ListMandatory []stsmdt.Mandatory
func New(m ...stsmdt.Mandatory) ListMandatory {
res := make([]stsmdt.Mandatory, 0)
copy(res, m)
return res
}

View File

@@ -0,0 +1,126 @@
/*
* 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 listmandatory
import (
stsctr "github.com/nabbar/golib/status/control"
stsmdt "github.com/nabbar/golib/status/mandatory"
)
func (l *ListMandatory) Walk(fct func(m stsmdt.Mandatory) bool) {
if l == nil {
return
} else if len(*l) < 1 {
return
}
var (
k bool
m stsmdt.Mandatory
n = *l
)
for i := range n {
m = n[i]
k = fct(m)
n[i] = m
if !k {
break
}
}
*l = n
}
func (l *ListMandatory) Add(m ...stsmdt.Mandatory) {
if l == nil {
return
}
var n = *l
if len(n) < 1 {
n = make([]stsmdt.Mandatory, 0)
}
*l = append(n, m...)
}
func (l *ListMandatory) Del(m stsmdt.Mandatory) {
if l == nil {
return
}
var (
n = *l
r = make([]stsmdt.Mandatory, 0)
)
if len(n) < 1 {
*l = make([]stsmdt.Mandatory, 0)
return
}
for i := range n {
if n[i] != m {
r = append(r, n[i])
}
}
*l = r
}
func (l ListMandatory) GetMode(key string) stsctr.Mode {
if len(l) < 1 {
return stsctr.Ignore
}
for i := range l {
if l[i].KeyHas(key) {
return l[i].GetMode()
}
}
return stsctr.Ignore
}
func (l *ListMandatory) SetMode(key string, mod stsctr.Mode) {
if len(*l) < 1 {
return
}
var n = *l
for i := range n {
if n[i].KeyHas(key) {
n[i].SetMode(mod)
*l = n
return
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 mandatory
import (
"sync/atomic"
stsctr "github.com/nabbar/golib/status/control"
)
type Mandatory interface {
SetMode(m stsctr.Mode)
GetMode() stsctr.Mode
KeyHas(key string) bool
KeyAdd(keys ...string)
KeyDel(keys ...string)
KeyList() []string
}
func New() Mandatory {
m := new(atomic.Value)
m.Store(stsctr.Ignore)
k := new(atomic.Value)
k.Store(make([]string, 0))
return &model{
Mode: m,
Keys: k,
}
}

135
status/mandatory/model.go Normal file
View File

@@ -0,0 +1,135 @@
/*
* 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 mandatory
import (
"sync/atomic"
stsctr "github.com/nabbar/golib/status/control"
"golang.org/x/exp/slices"
)
type model struct {
Mode *atomic.Value
Keys *atomic.Value
}
func (o *model) SetMode(m stsctr.Mode) {
o.Mode.Store(m)
}
func (o *model) GetMode() stsctr.Mode {
m := o.Mode.Load()
if m != nil {
return m.(stsctr.Mode)
}
return stsctr.Ignore
}
func (o *model) KeyHas(key string) bool {
i := o.Keys.Load()
if i == nil {
return false
} else if l, k := i.([]string); !k {
return false
} else {
return slices.Contains(l, key)
}
}
func (o *model) KeyAdd(keys ...string) {
var (
i any
k bool
l []string
)
i = o.Keys.Load()
if i == nil {
l = make([]string, 0)
} else if l, k = i.([]string); !k {
l = make([]string, 0)
}
for _, key := range keys {
if !slices.Contains(l, key) {
l = append(l, key)
}
}
o.Keys.Store(l)
}
func (o *model) KeyDel(keys ...string) {
var (
i any
k bool
l []string
)
i = o.Keys.Load()
if i == nil {
o.Keys.Store(make([]string, 0))
return
} else if l, k = i.([]string); !k {
o.Keys.Store(make([]string, 0))
return
}
var res = make([]string, 0)
for _, key := range l {
if !slices.Contains(keys, key) {
res = append(res, key)
}
}
o.Keys.Store(res)
}
func (o *model) KeyList() []string {
var (
i any
k bool
l []string
)
i = o.Keys.Load()
if i == nil {
return make([]string, 0)
} else if l, k = i.([]string); !k {
return make([]string, 0)
}
return slices.Clone(l)
}

View File

@@ -30,12 +30,11 @@ import (
"sync"
"time"
liberr "github.com/nabbar/golib/errors"
montps "github.com/nabbar/golib/monitor/types"
libctx "github.com/nabbar/golib/context"
liberr "github.com/nabbar/golib/errors"
monsts "github.com/nabbar/golib/monitor/status"
montps "github.com/nabbar/golib/monitor/types"
stsctr "github.com/nabbar/golib/status/control"
"golang.org/x/exp/slices"
)
@@ -74,28 +73,60 @@ func (o *sts) IsHealthy(name ...string) bool {
}
func (o *sts) getStatus(keys ...string) (monsts.Status, string) {
if len(keys) < 1 {
keys = o.cfgGetMandatory()
}
o.m.RLock()
defer o.m.RUnlock()
s := monsts.OK
m := ""
stt := monsts.OK
msg := ""
ign := make([]string, 0)
o.MonitorWalk(func(name string, val montps.Monitor) bool {
if !slices.Contains(keys, name) {
if len(keys) > 0 && !slices.Contains(keys, name) {
return true
} else if len(ign) > 0 && slices.Contains(ign, name) {
return true
}
if v := val.Status(); s > v {
s = v
m = val.Message()
v := val.Status()
if c := o.cfgGetMode(name); c == stsctr.Ignore {
return true
} else if c == stsctr.Should && v < monsts.Warn {
if stt > monsts.Warn {
stt = monsts.Warn
msg = val.Message()
}
} else if c == stsctr.One {
lst := o.cfgGetOne(name)
sta := monsts.KO
res := ""
o.MonitorWalk(func(nme string, val montps.Monitor) bool {
if !slices.Contains(lst, nme) {
return true
}
ign = append(ign, nme)
w := val.Status()
if w > sta {
sta = w
} else if w == sta && len(res) < 1 {
res = val.Message()
}
return true
})
if stt > sta {
stt = sta
msg = res
}
} else if stt > v {
stt = v
msg = val.Message()
}
return true
})
return s, m
return stt, msg
}

View File

@@ -31,9 +31,8 @@ import (
"strconv"
"strings"
liberr "github.com/nabbar/golib/errors"
ginsdk "github.com/gin-gonic/gin"
liberr "github.com/nabbar/golib/errors"
)
const (