diff options
| -rw-r--r-- | TODO.md | 18 | ||||
| -rw-r--r-- | internal/clients/args.go | 28 | ||||
| -rw-r--r-- | internal/datas/rbuffer.go | 49 | ||||
| -rw-r--r-- | internal/datas/rbuffer_test.go | 106 | ||||
| -rw-r--r-- | internal/options/options.go | 4 | ||||
| -rw-r--r-- | internal/ssh/client/authmethods.go | 10 |
6 files changed, 193 insertions, 22 deletions
diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 4bfad52..0000000 --- a/TODO.md +++ /dev/null @@ -1,18 +0,0 @@ -TODO -==== - -This is a loose list of what to do. Maybe for the next releae or maybe for a later one. - -[ ] Client 4.x should print an error and exit when trying to connect to a 3.x server. -[ ] Client 3.x should print an error and exit when trying to connect to a 4.x server. -[ ] Create a GitHub Wiki - [ ] Migrate existing documentation + update animated Gifs - [ ] Document that can use additional args as file lists - [ ] Document spartan mode - [ ] Document serverless mode - [ ] Document color configuratio - [ ] Go through the git history and document more stuff -[ ] Manual test/adjust dtail colors -[ ] Integration test for dtail in serverless mode -[ ] Document how to run ingeration tests -[ ] dserver scheduled queries integration test diff --git a/internal/clients/args.go b/internal/clients/args.go new file mode 100644 index 0000000..684dadd --- /dev/null +++ b/internal/clients/args.go @@ -0,0 +1,28 @@ +package clients + +import ( + "github.com/mimecast/dtail/internal/lcontext" + "github.com/mimecast/dtail/internal/omode" + + gossh "golang.org/x/crypto/ssh" +) + +// Args is a helper struct to summarize common client arguments. +type Args struct { + lcontext.LContext + RegexStr string + Mode omode.Mode + ServersStr string + UserName string + What string + Arguments []string + RegexInvert bool + TrustAllHosts bool + Discovery string + ConnectionsPerCPU int + Timeout int + SSHAuthMethods []gossh.AuthMethod + SSHHostKeyCallback gossh.HostKeyCallback + PrivateKeyPathFile string + Quiet bool +} diff --git a/internal/datas/rbuffer.go b/internal/datas/rbuffer.go new file mode 100644 index 0000000..df8f622 --- /dev/null +++ b/internal/datas/rbuffer.go @@ -0,0 +1,49 @@ +package datas + +import "fmt" + +// RBuffer is a simple circular string ring buffer data structure. +type RBuffer struct { + Capacity int + size int + readPos int + writePos int + data []string +} + +// NewRBuffer creates a new string ring buffer. +func NewRBuffer(capacity int) (*RBuffer, error) { + if capacity < 1 { + return nil, fmt.Errorf("RBuffer capacity must not be less than 1") + } + + r := RBuffer{ + Capacity: capacity, + size: capacity + 1, + data: make([]string, capacity+1), + } + + return &r, nil +} + +// Add a value. +func (r *RBuffer) Add(value string) { + r.data[r.writePos] = value + r.writePos = (r.writePos + 1) % r.size + + if r.writePos == r.readPos { + r.readPos = (r.readPos + 1) % r.size + } +} + +// Get a value. +func (r *RBuffer) Get() (string, bool) { + if r.readPos == r.writePos { + // RBuffer is empty. + return "", false + } + + value := r.data[r.readPos] + r.readPos = (r.readPos + 1) % r.size + return value, true +} diff --git a/internal/datas/rbuffer_test.go b/internal/datas/rbuffer_test.go new file mode 100644 index 0000000..843bb8e --- /dev/null +++ b/internal/datas/rbuffer_test.go @@ -0,0 +1,106 @@ +package datas + +import ( + "fmt" + "math/rand" + "testing" + "time" +) + +func TestRBufferOneElement(t *testing.T) { + r, err := NewRBuffer(1) + if err != nil { + t.Errorf("Expected error creating ring buffer with capacity 1") + } + + testRBufferValues(t, r, []string{"Hello world"}) + testRBufferValues(t, r, []string{"Hello world", "Hello universe"}) +} + +func TestRBuffer(t *testing.T) { + if _, err := NewRBuffer(0); err == nil { + t.Errorf("Expected error creating ring buffer with capacity 0") + } + + r, err := NewRBuffer(10) + if err != nil { + t.Errorf("Error creating ring buffer with capacity 10: %v", err) + } + + fiveValues := []string{ + "42 is the answer!", + "Scorpion: Get over here!", + "Have you swiped your nectar card?", + "Please mind the gap between the train and the platform!", + "Visit DTail at https://dtail.dev", + } + testRBufferValues(t, r, fiveValues) + + moreFiveValues := []string{ + "I love Golang", + "As a contrast, I also love Perl", + "Mimecast: Stop Bad Things From Happening to Good Organizations", + "We are the Buetow Brothers", + "London is calling", + } + tenValues := append(fiveValues, moreFiveValues...) + testRBufferValues(t, r, tenValues) +} + +func TestRandomRBuffer(t *testing.T) { + for i := 0; i < 100; i++ { + testRandomRBuffer(t) + } +} + +func testRandomRBuffer(t *testing.T) { + rand.Seed(time.Now().UnixNano()) + + maxCapacity := 1000 + minCapacity := 1 + capacity := rand.Intn(maxCapacity-minCapacity) + minCapacity + r, err := NewRBuffer(capacity) + if err != nil { + t.Errorf("Error creating ring buffer with capacity %d: %v", capacity, err) + } + + numValues := rand.Intn(capacity * 2) + values := make([]string, numValues) + for i := 0; i < numValues; i++ { + values = append(values, fmt.Sprintf("%d.%d", i, rand.Int())) + } + + testRBufferValues(t, r, values) +} + +func testRBufferValues(t *testing.T, r *RBuffer, values []string) { + value, ok := r.Get() + if ok { + t.Errorf("Expected not ok reading from empty ring buffer but got ok and value '%s'", value) + } + + for _, value := range values { + r.Add(value) + } + + expectedValues := values + overCapacity := len(values) - r.Capacity + if overCapacity > 0 { + expectedValues = values[overCapacity:] + } + + for _, expected := range expectedValues { + value, ok := r.Get() + if !ok { + t.Errorf("Expected value '%s' but got nothing", expected) + } + if value != expected { + t.Errorf("Expected value '%s' but got value '%v'", expected, value) + } + } + + value, ok = r.Get() + if ok { + t.Errorf("Expected not ok reading from empty ring buffer but got ok and value '%s'", value) + } +} diff --git a/internal/options/options.go b/internal/options/options.go new file mode 100644 index 0000000..9eb4501 --- /dev/null +++ b/internal/options/options.go @@ -0,0 +1,4 @@ +package options + +// Options is a map of all options specified by a DTail client to be transferred to the DTail server (e.g. such as grep context control such as -after, -before and -max). +type Options map[string]string diff --git a/internal/ssh/client/authmethods.go b/internal/ssh/client/authmethods.go index b1e514d..37f8382 100644 --- a/internal/ssh/client/authmethods.go +++ b/internal/ssh/client/authmethods.go @@ -36,10 +36,12 @@ func initKnownHostsAuthMethods(trustAllHosts bool, throttleCh chan struct{}, dlog.Client.FatalPanic(knownHostsPath, err) } dlog.Client.Debug("initKnownHostsAuthMethods", "Added known hosts file path", knownHostsPath) - if config.Client.ExperimentalFeaturesEnable { - sshAuthMethods = append(sshAuthMethods, gossh.Password("experimental feature test")) - dlog.Client.Debug("initKnownHostsAuthMethods", "Added experimental method to list of auth methods") - } + /* + if config.Client.ExperimentalFeaturesEnable { + sshAuthMethods = append(sshAuthMethods, gossh.Password("experimental feature test")) + dlog.Client.Debug("initKnownHostsAuthMethods", "Added experimental method to list of auth methods") + } + */ // First try to read custom private key path. if privateKeyPath != "" { |
