summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <pbuetow@mimecast.com>2021-10-21 21:28:49 +0300
committerPaul Buetow <pbuetow@mimecast.com>2021-10-21 21:28:49 +0300
commitf4207a55f71bfbcfdc532d5cdd3befaa3474a157 (patch)
treeea5e4a2d2a67035f645bdee496ae55a52034178a /internal
parentd80d6070557e3a800e3a54967af9eced518f116b (diff)
parent739205206d63bf42f4e843b39d04d4c8cd8207c3 (diff)
merge develop
Diffstat (limited to 'internal')
-rw-r--r--internal/clients/baseclient.go131
-rw-r--r--internal/clients/catclient.go16
-rw-r--r--internal/clients/connectors/connector.go17
-rw-r--r--internal/clients/connectors/serverconnection.go206
-rw-r--r--internal/clients/connectors/serverless.go116
-rw-r--r--internal/clients/grepclient.go19
-rw-r--r--internal/clients/handlers/basehandler.go77
-rw-r--r--internal/clients/handlers/clienthandler.go4
-rw-r--r--internal/clients/handlers/healthhandler.go106
-rw-r--r--internal/clients/handlers/maprhandler.go56
-rw-r--r--internal/clients/healthclient.go114
-rw-r--r--internal/clients/maker.go2
-rw-r--r--internal/clients/maprclient.go89
-rw-r--r--internal/clients/remote/connection.go212
-rw-r--r--internal/clients/stats.go76
-rw-r--r--internal/clients/tailclient.go20
-rw-r--r--internal/color/brush/brush.go194
-rw-r--r--internal/color/color.go174
-rw-r--r--internal/color/color_test.go53
-rw-r--r--internal/color/colorfy.go56
-rw-r--r--internal/color/paint.go91
-rw-r--r--internal/color/table.go53
-rw-r--r--internal/config/args.go164
-rw-r--r--internal/config/client.go194
-rw-r--r--internal/config/common.go26
-rw-r--r--internal/config/config.go71
-rw-r--r--internal/config/env.go7
-rw-r--r--internal/config/initializer.go184
-rw-r--r--internal/config/read.go37
-rw-r--r--internal/config/server.go10
-rw-r--r--internal/discovery/comma.go4
-rw-r--r--internal/discovery/discovery.go33
-rw-r--r--internal/discovery/file.go8
-rw-r--r--internal/done.go10
-rw-r--r--internal/io/dlog/dlog.go272
-rw-r--r--internal/io/dlog/level.go84
-rw-r--r--internal/io/dlog/loggers/factory.go54
-rw-r--r--internal/io/dlog/loggers/file.go165
-rw-r--r--internal/io/dlog/loggers/fout.go46
-rw-r--r--internal/io/dlog/loggers/logger.go19
-rw-r--r--internal/io/dlog/loggers/none.go21
-rw-r--r--internal/io/dlog/loggers/stdout.go54
-rw-r--r--internal/io/dlog/loggers/strategy.go35
-rw-r--r--internal/io/dlog/rotation.go27
-rw-r--r--internal/io/fs/catfile.go4
-rw-r--r--internal/io/fs/filereader.go6
-rw-r--r--internal/io/fs/filter.go167
-rw-r--r--internal/io/fs/permissions/permission.go4
-rw-r--r--internal/io/fs/permissions/permission_linuxacl.go2
-rw-r--r--internal/io/fs/readfile.go384
-rw-r--r--internal/io/fs/tailfile.go4
-rw-r--r--internal/io/fs/truncate.go61
-rw-r--r--internal/io/line/line.go5
-rw-r--r--internal/io/logger/logger.go403
-rw-r--r--internal/io/logger/modes.go12
-rw-r--r--internal/io/logger/strategy.go22
-rw-r--r--internal/io/pool/builder.go21
-rw-r--r--internal/io/pool/bytesbuffer.go22
-rw-r--r--internal/io/prompt/prompt.go13
-rw-r--r--internal/io/signal/signal.go8
-rw-r--r--internal/lcontext/lcontext.go2
-rw-r--r--internal/mapr/aggregateset.go29
-rw-r--r--internal/mapr/client/aggregate.go29
-rw-r--r--internal/mapr/funcs/function.go11
-rw-r--r--internal/mapr/funcs/function_test.go21
-rw-r--r--internal/mapr/funcs/maskdigits.go2
-rw-r--r--internal/mapr/globalgroupset.go11
-rw-r--r--internal/mapr/groupset.go291
-rw-r--r--internal/mapr/logformat/default.go41
-rw-r--r--internal/mapr/logformat/default_test.go88
-rw-r--r--internal/mapr/logformat/generickv.go31
-rw-r--r--internal/mapr/logformat/parser.go15
-rw-r--r--internal/mapr/query.go21
-rw-r--r--internal/mapr/query_test.go125
-rw-r--r--internal/mapr/selectcondition.go12
-rw-r--r--internal/mapr/server/aggregate.go155
-rw-r--r--internal/mapr/setclause.go2
-rw-r--r--internal/mapr/setcondition.go15
-rw-r--r--internal/mapr/token.go21
-rw-r--r--internal/mapr/whereclause.go16
-rw-r--r--internal/mapr/wherecondition.go30
-rw-r--r--internal/protocol/protocol.go18
-rw-r--r--internal/regex/regex.go20
-rw-r--r--internal/regex/regex_test.go33
-rw-r--r--internal/server/continuous.go36
-rw-r--r--internal/server/handlers/basehandler.go320
-rw-r--r--internal/server/handlers/controlhandler.go98
-rw-r--r--internal/server/handlers/healthhandler.go58
-rw-r--r--internal/server/handlers/mapcommand.go7
-rw-r--r--internal/server/handlers/readcommand.go83
-rw-r--r--internal/server/handlers/serverhandler.go412
-rw-r--r--internal/server/scheduler.go37
-rw-r--r--internal/server/server.go110
-rw-r--r--internal/server/stats.go21
-rw-r--r--internal/source/source.go30
-rw-r--r--internal/ssh/client/authmethods.go67
-rw-r--r--internal/ssh/client/customkeycallback.go3
-rw-r--r--internal/ssh/client/knownhostscallback.go38
-rw-r--r--internal/ssh/server/hostkey.go18
-rw-r--r--internal/ssh/server/publickeycallback.go38
-rw-r--r--internal/ssh/ssh.go11
-rw-r--r--internal/user/name.go3
-rw-r--r--internal/user/server/user.go57
-rw-r--r--internal/version/version.go34
104 files changed, 4357 insertions, 2708 deletions
diff --git a/internal/clients/baseclient.go b/internal/clients/baseclient.go
index f83fcfd..4a7bd84 100644
--- a/internal/clients/baseclient.go
+++ b/internal/clients/baseclient.go
@@ -2,15 +2,13 @@ package clients
import (
"context"
- "fmt"
- "strings"
"sync"
"time"
- "github.com/mimecast/dtail/internal/clients/remote"
+ "github.com/mimecast/dtail/internal/clients/connectors"
+ "github.com/mimecast/dtail/internal/config"
"github.com/mimecast/dtail/internal/discovery"
- "github.com/mimecast/dtail/internal/io/logger"
- "github.com/mimecast/dtail/internal/omode"
+ "github.com/mimecast/dtail/internal/io/dlog"
"github.com/mimecast/dtail/internal/regex"
"github.com/mimecast/dtail/internal/ssh/client"
@@ -19,13 +17,13 @@ import (
// This is the main client data structure.
type baseClient struct {
- Args
+ config.Args
// To display client side stats
stats *stats
// List of remote servers to connect to.
servers []string
// We have one connection per remote server.
- connections []*remote.Connection
+ connections []connectors.Connector
// SSH auth methods to use to connect to the remote servers.
sshAuthMethods []gossh.AuthMethod
// To deal with SSH host keys
@@ -41,7 +39,7 @@ type baseClient struct {
}
func (c *baseClient) init() {
- logger.Debug("Initiating base client")
+ dlog.Client.Debug("Initiating base client", c.Args.String())
flag := regex.Default
if c.Args.RegexInvert {
@@ -49,12 +47,16 @@ func (c *baseClient) init() {
}
regex, err := regex.New(c.Args.RegexStr, flag)
if err != nil {
- logger.FatalExit(c.Regex, "invalid regex!", err, regex)
+ dlog.Client.FatalPanic(c.Regex, "Invalid regex!", err, regex)
}
c.Regex = regex
- logger.Debug("Regex", c.Regex)
- c.sshAuthMethods, c.hostKeyCallback = client.InitSSHAuthMethods(c.Args.SSHAuthMethods, c.Args.SSHHostKeyCallback, c.Args.TrustAllHosts, c.throttleCh, c.Args.PrivateKeyPathFile)
+ if c.Args.Serverless {
+ return
+ }
+ c.sshAuthMethods, c.hostKeyCallback = client.InitSSHAuthMethods(
+ c.Args.SSHAuthMethods, c.Args.SSHHostKeyCallback, c.Args.TrustAllHosts,
+ c.throttleCh, c.Args.PrivateKeyPathFile)
}
func (c *baseClient) makeConnections(maker maker) {
@@ -62,26 +64,31 @@ func (c *baseClient) makeConnections(maker maker) {
discoveryService := discovery.New(c.Discovery, c.ServersStr, discovery.Shuffle)
for _, server := range discoveryService.ServerList() {
- c.connections = append(c.connections, c.makeConnection(server, c.sshAuthMethods, c.hostKeyCallback))
+ c.connections = append(c.connections, c.makeConnection(server,
+ c.sshAuthMethods, c.hostKeyCallback))
}
c.stats = newTailStats(len(c.connections))
}
func (c *baseClient) Start(ctx context.Context, statsCh <-chan string) (status int) {
- // Periodically check for unknown hosts, and ask the user whether to trust them or not.
- go c.hostKeyCallback.PromptAddHosts(ctx)
+ dlog.Client.Trace("Starting base client")
+ // Can be nil when serverless.
+ if c.hostKeyCallback != nil {
+ // Periodically check for unknown hosts, and ask the user whether to trust them or not.
+ go c.hostKeyCallback.PromptAddHosts(ctx)
+ }
// Print client stats every time something on statsCh is recieved.
go c.stats.Start(ctx, c.throttleCh, statsCh, c.Args.Quiet)
- // Keep count of active connections
- active := make(chan struct{}, len(c.connections))
+ var wg sync.WaitGroup
+ wg.Add(len(c.connections))
var mutex sync.Mutex
- for i, conn := range c.connections {
- go func(i int, conn *remote.Connection) {
- connStatus := c.start(ctx, active, i, conn)
- // Update global status.
+ for i, conn := range c.connections {
+ go func(i int, conn connectors.Connector) {
+ defer wg.Done()
+ connStatus := c.startConnection(ctx, i, conn)
mutex.Lock()
defer mutex.Unlock()
if connStatus > status {
@@ -90,15 +97,12 @@ func (c *baseClient) Start(ctx context.Context, statsCh <-chan string) (status i
}(i, conn)
}
- c.waitUntilDone(ctx, active)
+ wg.Wait()
return
}
-func (c *baseClient) start(ctx context.Context, active chan struct{}, i int, conn *remote.Connection) (status int) {
- // Increment connection count
- active <- struct{}{}
- // Derement connection count
- defer func() { <-active }()
+func (c *baseClient) startConnection(ctx context.Context, i int,
+ conn connectors.Connector) (status int) {
for {
connCtx, cancel := context.WithCancel(ctx)
@@ -106,80 +110,25 @@ func (c *baseClient) start(ctx context.Context, active chan struct{}, i int, con
conn.Start(connCtx, cancel, c.throttleCh, c.stats.connectionsEstCh)
// Retrieve status code from handler (dtail client will exit with that status)
- status = conn.Handler.Status()
+ status = conn.Handler().Status()
if !c.retry {
return
}
time.Sleep(time.Second * 2)
- logger.Debug(conn.Server, "Reconnecting")
-
- conn = c.makeConnection(conn.Server, c.sshAuthMethods, c.hostKeyCallback)
+ dlog.Client.Debug(conn.Server(), "Reconnecting")
+ conn = c.makeConnection(conn.Server(), c.sshAuthMethods, c.hostKeyCallback)
c.connections[i] = conn
}
}
-func (c *baseClient) makeCommandOptions() map[string]string {
- options := make(map[string]string)
-
- if c.Args.Quiet {
- options["quiet"] = fmt.Sprintf("%v", c.Args.Quiet)
- }
- if c.Args.LContext.MaxCount != 0 {
- options["max"] = fmt.Sprintf("%d", c.Args.LContext.MaxCount)
- }
- if c.Args.LContext.BeforeContext != 0 {
- options["before"] = fmt.Sprintf("%d", c.Args.LContext.BeforeContext)
- }
- if c.Args.LContext.AfterContext != 0 {
- options["after"] = fmt.Sprintf("%d", c.Args.LContext.AfterContext)
- }
-
- return options
-}
-
-func (c *baseClient) commandOptionsToString(options map[string]string) string {
- var sb strings.Builder
-
- count := 0
- for k, v := range options {
- if count > 0 {
- sb.WriteString(":")
- }
- sb.WriteString(fmt.Sprintf("%s=%s", k, v))
- count++
- }
-
- return sb.String()
-}
-
-func (c *baseClient) makeConnection(server string, sshAuthMethods []gossh.AuthMethod, hostKeyCallback client.HostKeyCallback) *remote.Connection {
- conn := remote.NewConnection(server, c.UserName, sshAuthMethods, hostKeyCallback)
- conn.Handler = c.maker.makeHandler(server)
- conn.Commands = c.maker.makeCommands(c.makeCommandOptions())
-
- return conn
-}
-
-func (c *baseClient) waitUntilDone(ctx context.Context, active chan struct{}) {
- defer logger.Debug("Terminated connection")
-
- // We want to have at least one active connection
- <-active
- // Put it back on the channel
- active <- struct{}{}
-
- if c.Mode == omode.TailClient && c.retry {
- <-ctx.Done()
- }
-
- for {
- numActive := len(active)
- if numActive == 0 {
- return
- }
- logger.Debug("Active connections", numActive)
- time.Sleep(time.Second)
+func (c *baseClient) makeConnection(server string, sshAuthMethods []gossh.AuthMethod,
+ hostKeyCallback client.HostKeyCallback) connectors.Connector {
+ if c.Args.Serverless {
+ return connectors.NewServerless(c.UserName, c.maker.makeHandler(server),
+ c.maker.makeCommands())
}
+ return connectors.NewServerConnection(server, c.UserName, sshAuthMethods,
+ hostKeyCallback, c.maker.makeHandler(server), c.maker.makeCommands())
}
diff --git a/internal/clients/catclient.go b/internal/clients/catclient.go
index db892f1..bd65560 100644
--- a/internal/clients/catclient.go
+++ b/internal/clients/catclient.go
@@ -7,6 +7,8 @@ import (
"strings"
"github.com/mimecast/dtail/internal/clients/handlers"
+ "github.com/mimecast/dtail/internal/config"
+ "github.com/mimecast/dtail/internal/io/dlog"
"github.com/mimecast/dtail/internal/omode"
)
@@ -16,11 +18,10 @@ type CatClient struct {
}
// NewCatClient returns a new cat client.
-func NewCatClient(args Args) (*CatClient, error) {
+func NewCatClient(args config.Args) (*CatClient, error) {
if args.RegexStr != "" {
return nil, errors.New("Can't use regex with 'cat' operating mode")
}
-
args.Mode = omode.CatClient
c := CatClient{
@@ -33,7 +34,6 @@ func NewCatClient(args Args) (*CatClient, error) {
c.init()
c.makeConnections(c)
-
return &c, nil
}
@@ -41,10 +41,14 @@ func (c CatClient) makeHandler(server string) handlers.Handler {
return handlers.NewClientHandler(server)
}
-func (c CatClient) makeCommands(options map[string]string) (commands []string) {
- optionsStr := c.commandOptionsToString(options)
+func (c CatClient) makeCommands() (commands []string) {
+ regex, err := c.Regex.Serialize()
+ if err != nil {
+ dlog.Client.FatalPanic(err)
+ }
for _, file := range strings.Split(c.What, ",") {
- commands = append(commands, fmt.Sprintf("%s:%s %s %s", c.Mode.String(), optionsStr, file, c.Regex.Serialize()))
+ commands = append(commands, fmt.Sprintf("%s:%s %s %s",
+ c.Mode.String(), c.Args.SerializeOptions(), file, regex))
}
return
}
diff --git a/internal/clients/connectors/connector.go b/internal/clients/connectors/connector.go
new file mode 100644
index 0000000..3ab6a08
--- /dev/null
+++ b/internal/clients/connectors/connector.go
@@ -0,0 +1,17 @@
+package connectors
+
+import (
+ "context"
+
+ "github.com/mimecast/dtail/internal/clients/handlers"
+)
+
+// Connector interface.
+type Connector interface {
+ // Start the connection.
+ Start(ctx context.Context, cancel context.CancelFunc, thro