summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormatthieu <matthieu.cneude@gmail.com>2020-06-07 13:30:27 +0200
committermatthieu <matthieu.cneude@gmail.com>2020-06-07 13:30:27 +0200
commit577c36ff06f765122c743616865d701e8fb431b1 (patch)
treefa42a97894cdaaf6beec9506b109f9751b4c3296
parent70df0f0fc7b7611b6dac09486c705ccaf15a692d (diff)
Add generic output as a bar diagram from any command line input
-rw-r--r--internal/host_widget.go44
-rw-r--r--internal/platform/host.go90
-rw-r--r--internal/platform/host_test.go65
3 files changed, 167 insertions, 32 deletions
diff --git a/internal/host_widget.go b/internal/host_widget.go
index 11de304..8d94fe9 100644
--- a/internal/host_widget.go
+++ b/internal/host_widget.go
@@ -28,6 +28,7 @@ const (
rhTable = "rh.table"
rhBox = "rh.box"
rhGauge = "rh.gauge"
+ rhBar = "rh.bar"
)
type HostWidget struct {
@@ -87,6 +88,8 @@ func (ms *HostWidget) CreateWidgets(widget Widget, tui *Tui) (f func() error, er
f, err = ms.box(widget)
case rhGauge:
f, err = ms.gauge(widget)
+ case rhBar:
+ f, err = ms.bar(widget)
default:
return nil, errors.Errorf("can't find the widget %s", widget.Name)
}
@@ -409,6 +412,12 @@ func (ms *HostWidget) tableDisk(widget Widget) (f func() error, err error) {
}
headers := []string{"Filesystem", "Size", "Used", "Available", "Use%", "Mount"}
+ if _, ok := widget.Options[optionHeaders]; ok {
+ if len(widget.Options[optionHeaders]) > 0 {
+ headers = strings.Split(strings.TrimSpace(widget.Options[optionHeaders]), ",")
+ }
+ }
+
data, err := platform.HostDisk(ms.service.Runner, headers, unit)
if err != nil {
return nil, err
@@ -501,3 +510,38 @@ func (ms *HostWidget) gauge(widget Widget) (f func() error, err error) {
return
}
+
+func (ms *HostWidget) bar(widget Widget) (f func() error, err error) {
+ title := " Example of bar "
+ if _, ok := widget.Options[optionTitle]; ok {
+ title = widget.Options[optionTitle]
+ }
+
+ headers := []string{"small", "bigger", "big", "insane"}
+ if _, ok := widget.Options[optionHeaders]; ok {
+ if len(widget.Options[optionHeaders]) > 0 {
+ headers = strings.Split(strings.TrimSpace(widget.Options[optionHeaders]), ",")
+ }
+ }
+
+ cmd := "echo -e 20 30 40 50"
+ if _, ok := widget.Options[optionCommand]; ok {
+ cmd = widget.Options[optionCommand]
+ }
+
+ data, err := platform.HostBar(ms.service.Runner, cmd)
+ if err != nil {
+ return nil, err
+ }
+
+ f = func() error {
+ return ms.tui.AddBarChart(
+ data,
+ headers,
+ title,
+ widget.Options,
+ )
+ }
+
+ return
+}
diff --git a/internal/platform/host.go b/internal/platform/host.go
index df3b503..8daf632 100644
--- a/internal/platform/host.go
+++ b/internal/platform/host.go
@@ -364,37 +364,6 @@ func HostNetIO(runner runnerFunc, unit string) (string, error) {
return rx + " / " + tx, nil
}
-func HostTable(runner runnerFunc, command string, headers []string) (cells [][]string, err error) {
- lines, err := runner(command)
- if err != nil {
- return nil, err
- }
-
- scanner := bufio.NewScanner(strings.NewReader(lines))
- data := ""
-
- lineNumber := 0
- for scanner.Scan() {
- line := scanner.Text()
- parts := strings.Fields(line)
-
- if len(headers) == 0 {
- headers = parts
- lineNumber++
- continue
- }
-
- data += strings.Join(parts, ",") + ","
- lineNumber++
- }
- data = strings.Trim(data, ",")
-
- cells = [][]string{headers}
- cells = append(cells, formatToTable(len(headers), data)...)
-
- return
-}
-
func HostDisk(runner runnerFunc, headers []string, unit string) ([][]string, error) {
// GetIOStat returns io stat
lines, err := runner("/bin/df -x devtmpfs -x tmpfs -x debugfs")
@@ -448,7 +417,6 @@ func HostDisk(runner runnerFunc, headers []string, unit string) ([][]string, err
return c, nil
}
-
func HostDiskIO(runner runnerFunc, unit string) (string, error) {
// GetIOStat returns io stat
lines, err := runner("/bin/cat /proc/diskstats")
@@ -485,6 +453,33 @@ func HostDiskIO(runner runnerFunc, unit string) (string, error) {
return strconv.FormatFloat(fr, 'f', 2, strconv.IntSize) + " / " + strconv.FormatFloat(fw, 'f', 2, strconv.IntSize), nil
}
+func HostBar(runner runnerFunc, command string) (data []int, err error) {
+ lines, err := runner(command)
+ if err != nil {
+ return nil, err
+ }
+
+ scanner := bufio.NewScanner(strings.NewReader(lines))
+ lineNumber := 0
+ str := ""
+ for scanner.Scan() {
+ line := scanner.Text()
+ parts := strings.Fields(line)
+
+ for _, v := range parts {
+ str += v + ","
+ }
+ lineNumber++
+ }
+
+ f := formatToBar(str)
+ result := []int{}
+ for _, f := range f {
+ result = append(result, int(f))
+ }
+ return result, nil
+}
+
func HostBox(runner runnerFunc, command string) (string, error) {
lines, err := runner(command)
if err != nil {
@@ -516,6 +511,37 @@ func HostGauge(runner runnerFunc, command string) (float64, error) {
return 0, nil
}
+func HostTable(runner runnerFunc, command string, headers []string) (cells [][]string, err error) {
+ lines, err := runner(command)
+ if err != nil {
+ return nil, err
+ }
+
+ scanner := bufio.NewScanner(strings.NewReader(lines))
+ data := ""
+
+ lineNumber := 0
+ for scanner.Scan() {
+ line := scanner.Text()
+ parts := strings.Fields(line)
+
+ if len(headers) == 0 {
+ headers = parts
+ lineNumber++
+ continue
+ }
+
+ data += strings.Join(parts, ",") + ","
+ lineNumber++
+ }
+ data = strings.Trim(data, ",")
+
+ cells = [][]string{headers}
+ cells = append(cells, formatToTable(len(headers), data)...)
+
+ return
+}
+
func formatToBar(data string) (val []uint64) {
data = strings.Trim(data, ",")
s := strings.Split(data, ",")
diff --git a/internal/platform/host_test.go b/internal/platform/host_test.go
index 42c5a23..4d1c6dd 100644
--- a/internal/platform/host_test.go
+++ b/internal/platform/host_test.go
@@ -724,3 +724,68 @@ func Test_HostGauge(t *testing.T) {
})
}
}
+func Test_HostBar(t *testing.T) {
+ testCases := []struct {
+ name string
+ runner runnerFunc
+ expected []int
+ command string
+ wantErr bool
+ }{
+ {
+ name: "happy case",
+ expected: []int{40, 50, 60, 70},
+ runner: func(cmd string) (string, error) {
+ return "40 50 60 70", nil
+ },
+ wantErr: false,
+ },
+ {
+ name: "on multiple lines",
+ expected: []int{40, 50, 60, 70},
+ runner: func(cmd string) (string, error) {
+ return `40 50
+ 60 70`, nil
+ },
+ wantErr: false,
+ },
+ {
+ name: "empty result",
+ expected: []int{0},
+ runner: func(cmd string) (string, error) {
+ return "", nil
+ },
+ wantErr: false,
+ },
+ {
+ name: "runner return wrong result",
+ expected: []int{0},
+ runner: func(cmd string) (string, error) {
+ return "ldfsjsdf", nil
+ },
+ wantErr: false,
+ },
+ {
+ name: "runner return error",
+ command: "kb",
+ runner: func(cmd string) (string, error) {
+ return "60", errors.New("Error")
+ },
+ wantErr: true,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ actual, err := HostBar(tc.runner, tc.command)
+ if (err != nil) != tc.wantErr {
+ t.Errorf("Error '%v' even if wantErr is %t", err, tc.wantErr)
+ return
+ }
+
+ if tc.wantErr == false && !reflect.DeepEqual(actual, tc.expected) {
+ t.Errorf("Expected %v, actual %v", tc.expected, actual)
+ }
+ })
+ }
+}