2021-02-15 20:37:16 +01:00
package utils
import (
2021-06-13 12:03:36 +02:00
"bufio"
2021-02-15 20:37:16 +01:00
"bytes"
2022-02-06 15:37:50 +01:00
"database/sql"
2021-02-20 19:09:41 +01:00
"fmt"
2021-02-20 22:43:27 +01:00
"io"
2021-02-15 20:37:16 +01:00
"log"
2021-02-20 22:43:27 +01:00
"os"
2021-02-15 20:37:16 +01:00
"os/exec"
2021-06-13 12:03:36 +02:00
"strings"
2021-05-30 13:28:42 +02:00
"time"
2021-02-20 19:09:41 +01:00
2021-02-17 12:10:15 +01:00
"github.com/joho/godotenv"
2021-02-15 20:37:16 +01:00
)
2021-02-20 22:43:27 +01:00
// ExecAndStream : Runs a terminal command, but streams progress instead of outputting. Ideal for long lived process that need to be logged.
2023-05-29 21:52:27 +02:00
func ExecAndStream ( path string , command string , args [ ] string ) string {
2021-02-20 22:43:27 +01:00
cmd := exec . Command ( command , args ... )
var stdoutBuf , stderrBuf bytes . Buffer
cmd . Stdout = io . MultiWriter ( os . Stdout , & stdoutBuf )
cmd . Stderr = io . MultiWriter ( os . Stderr , & stderrBuf )
2021-06-13 12:03:36 +02:00
cmd . Dir = path
2021-02-20 22:43:27 +01:00
err := cmd . Run ( )
2023-05-29 21:52:27 +02:00
outStr , errStr := string ( stdoutBuf . Bytes ( ) ) , string ( stderrBuf . Bytes ( ) )
returnVal := outStr
2021-02-20 22:43:27 +01:00
if err != nil {
2021-06-13 12:03:36 +02:00
fmt . Printf ( "cmd.Run() failed with %s\n" , err )
2023-05-29 21:52:27 +02:00
returnVal = errStr
2021-02-20 22:43:27 +01:00
}
fmt . Printf ( "\nout:\n%s\nerr:\n%s\n" , outStr , errStr )
2023-05-29 21:52:27 +02:00
return returnVal
2021-02-20 22:43:27 +01:00
}
2021-02-15 20:37:16 +01:00
// Exec : Runs a terminal Command, catches and logs errors, returns the result.
2021-06-13 12:03:36 +02:00
func Exec ( path string , command string , args [ ] string ) string {
2021-02-15 20:37:16 +01:00
cmd := exec . Command ( command , args ... )
var out bytes . Buffer
var stderr bytes . Buffer
cmd . Stdout = & out
cmd . Stderr = & stderr
2021-06-13 12:03:36 +02:00
cmd . Dir = path
2021-02-15 20:37:16 +01:00
err := cmd . Run ( )
if err != nil {
2021-02-17 13:34:53 +01:00
// TODO: Deal with possibility of error in command, allow explicit error handling and return proper formatted stderr
2021-02-21 00:55:59 +01:00
// log.Println(fmt.Sprint(err) + ": " + stderr.String()) // ... Silence...
2021-02-15 20:37:16 +01:00
}
2021-02-17 01:08:10 +01:00
2021-02-21 00:55:59 +01:00
// log.Println("Result: " + out.String()) // ... Silence ...
2021-02-15 20:37:16 +01:00
2021-06-13 12:03:36 +02:00
return strings . Trim ( out . String ( ) , " \n" )
2021-02-17 01:08:10 +01:00
}
2021-06-13 12:03:36 +02:00
// 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
}
2021-02-17 01:08:10 +01:00
// DeleteEmptySlices : Given a string array, delete empty entries.
func DeleteEmptySlices ( s [ ] string ) [ ] string {
var r [ ] string
for _ , str := range s {
if str != "" {
r = append ( r , str )
}
}
return r
2021-02-15 20:37:16 +01:00
}
2021-02-17 12:10:15 +01:00
2021-05-02 10:52:32 +02:00
// GetSQLiteDbConnectionDetails : Returns the necessary string as connection info for SQL.db()
func GetSQLiteDbConnectionDetails ( ) string {
var apiEnv map [ string ] string
2022-10-08 18:41:37 +02:00
apiEnv , err := godotenv . Read ( GetPath ( ApiEnvFileLocation ) )
2021-05-02 10:52:32 +02:00
if err != nil {
log . Fatal ( "Error loading .env file" )
}
return apiEnv [ "SQLITE_DATABASE" ] // Will read from api project edgebox.env file
}
2021-05-30 13:28:42 +02:00
// GetSQLiteFormattedDateTime: Given a Time, Returns a string that is formatted ready to be inserted into an SQLite Datetime field using sql.Prepare.
func GetSQLiteFormattedDateTime ( t time . Time ) string {
// This date is used to indicate the layout.
const datetimeLayout = "2006-01-02 15:04:05"
formatedDatetime := t . Format ( datetimeLayout )
return formatedDatetime
}
2023-05-29 21:52:27 +02:00
const BackupPasswordFileLocation string = "backupPasswordFileLocation"
2022-10-08 18:41:37 +02:00
const CloudEnvFileLocation string = "cloudEnvFileLocation"
const ApiEnvFileLocation string = "apiEnvFileLocation"
const ApiPath string = "apiPath"
const EdgeAppsPath string = "edgeAppsPath"
2023-06-10 17:29:54 +02:00
const EdgeAppsBackupPath string = "edgeAppsBackupPath"
2022-10-08 18:41:37 +02:00
const WsPath string = "wsPath"
2024-12-08 21:16:33 +01:00
const BrowserDevPath string = "browserDevPath"
2023-10-29 20:48:14 +01:00
const LoggerPath string = "loggerPath"
2024-12-07 01:26:45 +01:00
const BrowserDevPasswordFileLocation string = "browserDevPasswordFileLocation"
const BrowserDevProxyPath string = "browserDevProxyPath"
2023-10-29 20:48:14 +01:00
2022-10-08 18:41:37 +02:00
2021-02-17 12:35:22 +01:00
// GetPath : Returns either the hardcoded path, or a overwritten value via .env file at project root. Register paths here for seamless working code between dev and prod environments ;)
func GetPath ( pathKey string ) string {
// Read whole of .env file to map.
var env map [ string ] string
env , err := godotenv . Read ( )
2021-06-13 12:03:36 +02:00
var targetPath string
2021-02-17 12:35:22 +01:00
if err != nil {
2021-06-13 12:03:36 +02:00
targetPath = ""
2021-02-17 12:35:22 +01:00
}
switch pathKey {
2022-10-08 18:41:37 +02:00
case CloudEnvFileLocation :
2022-02-06 15:37:50 +01:00
if env [ "CLOUD_ENV_FILE_LOCATION" ] != "" {
targetPath = env [ "CLOUD_ENV_FILE_LOCATION" ]
} else {
2023-11-05 02:01:16 +01:00
targetPath = "/home/system/components/api/cloud.env"
2022-02-06 15:37:50 +01:00
}
2022-10-08 18:41:37 +02:00
case ApiEnvFileLocation :
2021-02-17 12:35:22 +01:00
if env [ "API_ENV_FILE_LOCATION" ] != "" {
targetPath = env [ "API_ENV_FILE_LOCATION" ]
} else {
targetPath = "/home/system/components/api/edgebox.env"
}
2022-10-08 18:41:37 +02:00
case ApiPath :
2022-02-06 15:37:50 +01:00
if env [ "API_PATH" ] != "" {
2022-10-08 18:41:37 +02:00
targetPath = env [ "API_PATH" ]
2022-02-06 15:37:50 +01:00
} else {
targetPath = "/home/system/components/api/"
}
2022-10-08 18:41:37 +02:00
case EdgeAppsPath :
2021-02-17 12:35:22 +01:00
if env [ "EDGEAPPS_PATH" ] != "" {
targetPath = env [ "EDGEAPPS_PATH" ]
} else {
targetPath = "/home/system/components/apps/"
}
2023-06-10 17:29:54 +02:00
case EdgeAppsBackupPath :
if env [ "EDGEAPPS_BACKUP_PATH" ] != "" {
targetPath = env [ "EDGEAPPS_BACKUP_PATH" ]
} else {
targetPath = "/home/system/components/backups/"
}
2022-10-08 18:41:37 +02:00
case WsPath :
2021-02-17 12:35:22 +01:00
if env [ "WS_PATH" ] != "" {
targetPath = env [ "WS_PATH" ]
} else {
targetPath = "/home/system/components/ws/"
}
2024-12-08 21:16:33 +01:00
case BrowserDevPath :
if env [ "BROWSERDEV_PATH" ] != "" {
targetPath = env [ "BROWSERDEV_PATH" ]
} else {
targetPath = "/home/system/components/dev/"
}
2023-10-29 20:48:14 +01:00
case LoggerPath :
if env [ "LOGGER_PATH" ] != "" {
targetPath = env [ "LOGGER_PATH" ]
} else {
targetPath = "/home/system/components/logger/"
}
2023-05-29 21:52:27 +02:00
case BackupPasswordFileLocation :
if env [ "BACKUP_PASSWORD_FILE_LOCATION" ] != "" {
targetPath = env [ "BACKUP_PASSWORD_FILE_LOCATION" ]
} else {
targetPath = "/home/system/components/backups/pw.txt"
}
2024-12-07 01:26:45 +01:00
case BrowserDevPasswordFileLocation :
if env [ "BROWSERDEV_PASSWORD_FILE_LOCATION" ] != "" {
targetPath = env [ "BROWSERDEV_PASSWORD_FILE_LOCATION" ]
} else {
targetPath = "/root/.config/code-server/config.yaml"
}
case BrowserDevProxyPath :
if env [ "BROWSERDEV_PROXY_PATH" ] != "" {
targetPath = env [ "BROWSERDEV_PROXY_PATH" ]
} else {
targetPath = "/home/system/components/dev/"
}
2021-02-17 12:35:22 +01:00
default :
log . Printf ( "path_key %s nonexistant in GetPath().\n" , pathKey )
}
return targetPath
}
2022-02-06 15:37:50 +01:00
// WriteOption : Writes a key value pair option into the api shared database
func WriteOption ( optionKey string , optionValue string ) {
db , err := sql . Open ( "sqlite3" , GetSQLiteDbConnectionDetails ( ) )
if err != nil {
log . Fatal ( err . Error ( ) )
}
statement , err := db . Prepare ( "REPLACE into option (name, value, created, updated) VALUES (?, ?, ?, ?);" ) // Prepare SQL Statement
if err != nil {
log . Fatal ( err . Error ( ) )
}
formatedDatetime := GetSQLiteFormattedDateTime ( time . Now ( ) )
_ , err = statement . Exec ( optionKey , optionValue , formatedDatetime , formatedDatetime ) // Execute SQL Statement
if err != nil {
log . Fatal ( err . Error ( ) )
}
db . Close ( )
}
2023-03-20 00:54:42 +01:00
// ReadOption : Reads a key value pair option from the api shared database
func ReadOption ( optionKey string ) string {
db , err := sql . Open ( "sqlite3" , GetSQLiteDbConnectionDetails ( ) )
if err != nil {
log . Fatal ( err . Error ( ) )
}
var optionValue string
err = db . QueryRow ( "SELECT value FROM option WHERE name = ?" , optionKey ) . Scan ( & optionValue )
if err != nil {
2023-05-29 21:52:27 +02:00
log . Println ( err . Error ( ) )
2023-03-20 00:54:42 +01:00
}
db . Close ( )
return optionValue
}
// DeleteOption : Deletes a key value pair option from the api shared database
func DeleteOption ( optionKey string ) {
db , err := sql . Open ( "sqlite3" , GetSQLiteDbConnectionDetails ( ) )
if err != nil {
log . Fatal ( err . Error ( ) )
}
statement , err := db . Prepare ( "DELETE FROM option WHERE name = ?;" ) // Prepare SQL Statement
if err != nil {
log . Fatal ( err . Error ( ) )
}
_ , err = statement . Exec ( optionKey ) // Execute SQL Statement
if err != nil {
log . Fatal ( err . Error ( ) )
}
db . Close ( )
}