mirror of
https://github.com/edgebox-iot/edgeboxctl.git
synced 2026-09-25 06:13:03 +02:00
Storage Module Basis (#13)
* Added storage module, base structs, getDevices() func, taskGetStorageDevices (ticks every 30) * GetDevices now returns a complete description w/ disk partitions * Added InUse flag to Device, fixed logic bugs * Added disk space usage for partitions in use by the system * Cleanup * Added UsageStat and UsageSplit filling for in use devices * Changed value of lsblk block usage output to bytes * Cleanup, small fixes * Added ExecAndGetLines util func * Added explicit detection of disk or part block type, ignoring non-suppoorted devices * Added command line tool dependencies for the project in README file * Added comment to func ExecAndGetLines * Removed GetMySQLDbConnectionDetails() * Added tests to utils module * Fix invalid argument type for Exec family of tests * Removed too much verbosity from utils.GetPath when no env file is available, added new argument (path) to Exec family of funcs * Added new path argument to utils.Exec... test * Fixed TestExec * Added spaces trim to Exec result * Trimming spaces and newlines from result of Exec * Better visibility for test result log of TestExec * Added ExampleExecAndStream test * Added Example tests with failure status for ExecAndStream * Added branch to test for valid key in GetPath * Added missing t.Fail() statements in utils_test.go * Added storage_test.go file, smoke test * TestGetDevices
This commit is contained in:
+20
-28
@@ -1,31 +1,33 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
// ExecAndStream : Runs a terminal command, but streams progress instead of outputting. Ideal for long lived process that need to be logged.
|
||||
func ExecAndStream(command string, args []string) {
|
||||
func ExecAndStream(path string, command string, args []string) {
|
||||
|
||||
cmd := exec.Command(command, args...)
|
||||
|
||||
var stdoutBuf, stderrBuf bytes.Buffer
|
||||
cmd.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||
cmd.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
||||
cmd.Dir = GetPath("wsPath")
|
||||
cmd.Dir = path
|
||||
|
||||
err := cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("cmd.Run() failed with %s\n", err)
|
||||
fmt.Printf("cmd.Run() failed with %s\n", err)
|
||||
}
|
||||
|
||||
outStr, errStr := string(stdoutBuf.Bytes()), string(stderrBuf.Bytes())
|
||||
@@ -34,13 +36,13 @@ func ExecAndStream(command string, args []string) {
|
||||
}
|
||||
|
||||
// Exec : Runs a terminal Command, catches and logs errors, returns the result.
|
||||
func Exec(command string, args []string) string {
|
||||
func Exec(path string, command string, args []string) string {
|
||||
cmd := exec.Command(command, args...)
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
cmd.Dir = GetPath("wsPath")
|
||||
cmd.Dir = path
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
// TODO: Deal with possibility of error in command, allow explicit error handling and return proper formatted stderr
|
||||
@@ -49,10 +51,20 @@ func Exec(command string, args []string) string {
|
||||
|
||||
// log.Println("Result: " + out.String()) // ... Silence ...
|
||||
|
||||
return out.String()
|
||||
return strings.Trim(out.String(), " \n")
|
||||
|
||||
}
|
||||
|
||||
// Exec : Runs a terminal Command, returns the result as a *bufio.Scanner type, split in lines and ready to parse.
|
||||
func ExecAndGetLines(path string, command string, args []string) *bufio.Scanner {
|
||||
cmdOutput := Exec(path, command, args)
|
||||
cmdOutputReader := strings.NewReader(cmdOutput)
|
||||
scanner := bufio.NewScanner(cmdOutputReader)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
return scanner
|
||||
}
|
||||
|
||||
// DeleteEmptySlices : Given a string array, delete empty entries.
|
||||
func DeleteEmptySlices(s []string) []string {
|
||||
var r []string
|
||||
@@ -64,25 +76,6 @@ func DeleteEmptySlices(s []string) []string {
|
||||
return r
|
||||
}
|
||||
|
||||
// GetMySQLDbConnectionDetails : Returns the necessary string as connection info for SQL.db()
|
||||
func GetMySQLDbConnectionDetails() string {
|
||||
|
||||
var apiEnv map[string]string
|
||||
apiEnv, err := godotenv.Read(GetPath("apiEnvFileLocation"))
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Error loading .env file")
|
||||
}
|
||||
|
||||
Dbhost := "127.0.0.1:" + apiEnv["HOST_MACHINE_MYSQL_PORT"]
|
||||
Dbname := apiEnv["MYSQL_DATABASE"]
|
||||
Dbuser := apiEnv["MYSQL_USER"]
|
||||
Dbpass := apiEnv["MYSQL_PASSWORD"]
|
||||
|
||||
return Dbuser + ":" + Dbpass + "@tcp(" + Dbhost + ")/" + Dbname
|
||||
|
||||
}
|
||||
|
||||
// GetSQLiteDbConnectionDetails : Returns the necessary string as connection info for SQL.db()
|
||||
func GetSQLiteDbConnectionDetails() string {
|
||||
|
||||
@@ -112,11 +105,10 @@ func GetPath(pathKey string) string {
|
||||
// Read whole of .env file to map.
|
||||
var env map[string]string
|
||||
env, err := godotenv.Read()
|
||||
targetPath := ""
|
||||
var targetPath string
|
||||
|
||||
if err != nil {
|
||||
// log.Println("Project .env file not found withing project root. Using only hardcoded path variables.")
|
||||
// Do Nothing...
|
||||
targetPath = ""
|
||||
}
|
||||
|
||||
switch pathKey {
|
||||
|
||||
@@ -7,6 +7,96 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestExec(t *testing.T) {
|
||||
testCommand := "echo"
|
||||
testArguments := []string{"Hello World"}
|
||||
|
||||
result := Exec("/", testCommand, testArguments)
|
||||
|
||||
if result != "Hello World" {
|
||||
t.Log("Expected 'Hello World' but got", "'"+result+"'")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleExecAndStream() {
|
||||
ExecAndStream("/", "echo", []string{"Hello"})
|
||||
// Output:
|
||||
// Hello
|
||||
//
|
||||
// out:
|
||||
// Hello
|
||||
//
|
||||
// err:
|
||||
}
|
||||
|
||||
func ExampleExecAndStreamExecutableNotFound() {
|
||||
ExecAndStream("/", "testcommand", []string{"Hello"})
|
||||
// Output:
|
||||
// cmd.Run() failed with exec: "testcommand": executable file not found in $PATH
|
||||
//
|
||||
// out:
|
||||
//
|
||||
// err:
|
||||
}
|
||||
|
||||
func ExampleExecAndStreamError() {
|
||||
ExecAndStream("/", "man", []string{"Hello"})
|
||||
// Output:
|
||||
// cmd.Run() failed with exit status 16
|
||||
//
|
||||
// out:
|
||||
//
|
||||
// err:
|
||||
// No manual entry for Hello
|
||||
}
|
||||
|
||||
func TestExecAndGetLines(t *testing.T) {
|
||||
testCommand := "echo"
|
||||
testArguments := []string{"$'Line1\nLine2\nLine3'"}
|
||||
var result []string
|
||||
|
||||
scanner := ExecAndGetLines("/", testCommand, testArguments)
|
||||
|
||||
for scanner.Scan() {
|
||||
result = append(result, scanner.Text())
|
||||
}
|
||||
|
||||
if len(result) != 3 {
|
||||
t.Log("Expected 3 lines but got ", len(result))
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteEmptySlices(t *testing.T) {
|
||||
testSlice := []string{"Line1", "", "Line3"}
|
||||
|
||||
resultSlice := DeleteEmptySlices(testSlice)
|
||||
|
||||
if (len(resultSlice)) != 2 {
|
||||
t.Log("Expected 2 slices but got ", len(resultSlice))
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetPath(t *testing.T) {
|
||||
invalidPathKey := "test"
|
||||
|
||||
result := GetPath(invalidPathKey)
|
||||
if result != "" {
|
||||
t.Log("Expected empty result but got ", result)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
validPathKey := "wsPath"
|
||||
result = GetPath(validPathKey)
|
||||
if result != "/home/system/components/ws/" {
|
||||
t.Log("Expected /home/system/components/ws/ but got", result)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSQLiteFormattedDateTime(t *testing.T) {
|
||||
datetime := time.Date(2021, time.Month(1), 01, 1, 30, 15, 0, time.UTC)
|
||||
result := GetSQLiteFormattedDateTime(datetime)
|
||||
|
||||
Reference in New Issue
Block a user