Skip to content

Commit

Permalink
Migrate to stdout and auto create config file
Browse files Browse the repository at this point in the history
  • Loading branch information
Tzvonimir committed Apr 3, 2024
1 parent 65be3f8 commit 8535b44
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 85 deletions.
58 changes: 45 additions & 13 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"lda/config"
"lda/daemon"
"lda/database"
"lda/logging"
"lda/resources"
"lda/shell"
Expand Down Expand Up @@ -75,7 +76,7 @@ func init() {
includeShowFlagsForLda(ldaCmd)
includeShowFlagsForServe(serveCmd)

cobra.OnInitialize(initLogging)
cobra.OnInitialize(setupConfig)

ldaCmd.AddCommand(versionCmd)
ldaCmd.AddCommand(collectCmd)
Expand All @@ -95,13 +96,44 @@ func includeShowFlagsForServe(cmd *cobra.Command) {
cmd.Flags().StringP("port", "p", "8080", "Port to serve the frontend client")
}

func initLogging() {
func setupConfig() {

// setting up the system configuration
config.SetupSysConfig()

// setting up the operating system
config.SetupOs()

// setting up the shell
config.SetupShell()

// setting up the home directory
config.SetupHomeDir()

// setting up the LDA directory
config.SetupLdaDir()

// setting up the user permission level
config.SetupUserConfig()

// setting up optional application configuration
config.SetupConfig()

// setting up the LDA binary path
config.SetupLdaBinaryPath()

// setup database and run migrations
database.Setup()
database.RunMigrations()

// setting up the Logger
// TODO: consider adding verbose levels
if config.AppConfig.Debug || Verbose {
logging.Setup(os.Stdout, true)
} else {
logging.Setup(io.Discard, false)
}

}

// Execute is the entry point for the command line
Expand All @@ -119,37 +151,37 @@ func lda(cmd *cobra.Command, _ []string) {
}

func reload(_ *cobra.Command, _ []string) error {
fmt.Fprintln(config.AppConfig.Out, "Reloading LDA daemon...")
fmt.Fprintln(config.SysConfig.Out, "Reloading LDA daemon...")
if err := daemon.ReloadDaemon(); err != nil {
logging.Log.Error().Err(err).Msg("Failed to reload daemon")
return errors.Wrap(err, "failed to reload LDA daemon")
}
fmt.Fprintln(config.AppConfig.Out, "Reloading LDA daemon finished.")
fmt.Fprintln(config.SysConfig.Out, "Reloading LDA daemon finished.")
return nil
}

func start(_ *cobra.Command, _ []string) error {
fmt.Fprintln(config.AppConfig.Out, "Starting LDA daemon...")
fmt.Fprintln(config.SysConfig.Out, "Starting LDA daemon...")
if err := daemon.StartDaemon(); err != nil {
logging.Log.Error().Err(err).Msg("Failed to start daemon")
return errors.Wrap(err, "failed to start LDA daemon")
}
fmt.Fprintln(config.AppConfig.Out, "LDA daemon started.")
fmt.Fprintln(config.SysConfig.Out, "LDA daemon started.")
return nil
}

func stop(_ *cobra.Command, _ []string) error {
fmt.Fprintln(config.AppConfig.Out, "Stopping LDA daemon...")
fmt.Fprintln(config.SysConfig.Out, "Stopping LDA daemon...")
if err := daemon.StopDaemon(); err != nil {
logging.Log.Error().Err(err).Msg("Failed to stop daemon")
return errors.Wrap(err, "failed to stop LDA daemon")
}
fmt.Fprintln(config.AppConfig.Out, "LDA daemon stopped.")
fmt.Fprintln(config.SysConfig.Out, "LDA daemon stopped.")
return nil
}

func install(_ *cobra.Command, _ []string) error {
fmt.Fprintln(config.AppConfig.Out, "Installing LDA daemon...")
fmt.Fprintln(config.SysConfig.Out, "Installing LDA daemon...")
if err := daemon.InstallDaemonConfiguration(); err != nil {
logging.Log.Error().Err(err).Msg("Failed to install daemon configuration")
return errors.Wrap(err, "failed to install LDA daemon configuration file")
Expand All @@ -165,12 +197,12 @@ func install(_ *cobra.Command, _ []string) error {
return errors.Wrap(err, "failed to inject LDA shell source")
}

fmt.Fprintln(config.AppConfig.Out, "LDA daemon installed successfully.")
fmt.Fprintln(config.SysConfig.Out, "LDA daemon installed successfully.")
return nil
}

func uninstall(_ *cobra.Command, _ []string) error {
fmt.Fprintln(config.AppConfig.Out, "Uninstalling LDA daemon...")
fmt.Fprintln(config.SysConfig.Out, "Uninstalling LDA daemon...")
if err := daemon.DestroyDaemonConfiguration(); err != nil {
logging.Log.Error().Err(err).Msg("Failed to uninstall daemon configuration")
return errors.Wrap(err, "failed to uninstall LDA daemon configuration file")
Expand All @@ -181,7 +213,7 @@ func uninstall(_ *cobra.Command, _ []string) error {
return errors.Wrap(err, "failed to delete LDA shell configuration files")
}

fmt.Fprintln(config.AppConfig.Out, `Daemon service files and shell configuration deleted successfully,
fmt.Fprintln(config.SysConfig.Out, `Daemon service files and shell configuration deleted successfully,
~/.lda directory still holds database file, and your rc file stills has source script.
If you wish to remove those, delete them manually`)

Expand All @@ -191,7 +223,7 @@ func uninstall(_ *cobra.Command, _ []string) error {
func serve(cmd *cobra.Command, _ []string) error {
portFlag := cmd.Flag("port").Value

fmt.Fprintf(config.AppConfig.Out, "Serving local frontend client on http://localhost:%v\n", portFlag)
fmt.Fprintf(config.SysConfig.Out, "Serving local frontend client on http://localhost:%v\n", portFlag)

resources.Serve()

Expand Down
2 changes: 1 addition & 1 deletion cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ var (
)

func version(_ *cobra.Command, _ []string) {
fmt.Fprintf(config.AppConfig.Out, "LDA v%s\n", config.Version)
fmt.Fprintf(config.SysConfig.Out, "LDA v%s\n", config.Version)
}
13 changes: 13 additions & 0 deletions config/config.example.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
debug = false
#process_interval = 3600
#command_interval = 1
#command_interval_multiplier = 5
#max_concurrent_commands = 20
remote_collection = false
#server_host =
#server_port =
#exclude_regex =
#secure_connection =
#cert_file =
exclude_regex = "password"
process_collection_type = "ps"
47 changes: 36 additions & 11 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package config

import (
_ "embed"
"fmt"
"io"
"lda/logging"
"os"
"path/filepath"

"github.com/pkg/errors"

"github.com/spf13/viper"
)
Expand Down Expand Up @@ -32,24 +36,48 @@ type Config struct {
ExcludeRegex string `mapstructure:"exclude_regex"`
// ProcessCollectionType type of process collection to use, ps or psutil
ProcessCollectionType string `mapstructure:"process_collection_type"`
}

// Configuration that is not available via the configuration file

// SystemConfig Configuration that is not available via the configuration file
type SystemConfig struct {
// Out is the output writer for printing information
Out io.Writer
// ErrOut is the error output writer for printing errors
ErrOut io.Writer
}

// Embedding config file
//
//go:embed config.example.toml
var configExample string

// AppConfig is the global configuration instance
var AppConfig *Config

// SysConfig is the global system configuration instance
var SysConfig *SystemConfig

// SetupSysConfig initialize the system configuration instance
func SetupSysConfig() {
SysConfig = &SystemConfig{
// Set default output writers - currently we only use stdout and stderr, but this could potentially be changed
Out: os.Stdout,
ErrOut: os.Stderr,
}
}

// SetupConfig initialize the configuration instance
func SetupConfig() {

viper.SetConfigName("config")
viper.SetConfigType("toml")
viper.AddConfigPath(LdaDir)
configPath := filepath.Join(LdaDir, "config.toml")

if _, err := os.Stat(configPath); errors.Is(err, os.ErrNotExist) {
if err := os.WriteFile(configPath, []byte(configExample), 0644); err != nil {
fmt.Fprintf(SysConfig.ErrOut, "Failed to create config file: %s\n", err)
}
}

viper.SetConfigFile(configPath)

// Set default configuration values
var config = &Config{
Expand All @@ -60,17 +88,14 @@ func SetupConfig() {
CommandIntervalMultiplier: 5,
MaxConcurrentCommands: 20,
ProcessCollectionType: "ps",
// Set default output writers - currently we only use stdout and stderr, but this could potentially be changed
Out: os.Stdout,
ErrOut: os.Stderr,
}

if err := viper.ReadInConfig(); err != nil {
logging.Log.Error().Err(err).Msg("Failed to read config file")
fmt.Fprintf(SysConfig.ErrOut, "Failed to read config file: %s\n", err)
}

if err := viper.Unmarshal(config); err != nil {
logging.Log.Error().Err(err).Msg("Failed to unmarshal config file")
fmt.Fprintf(SysConfig.ErrOut, "Failed to unmarshal config: %s\n", err)
}

AppConfig = config
Expand Down
20 changes: 7 additions & 13 deletions config/os.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package config

import (
"lda/logging"
"fmt"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -50,14 +50,12 @@ func SetupOs() {
OSName = runtime.GOOS
switch OSName {
case "linux":
logging.Log.Info().Msg("Running on Linux")
OS = Linux
case "darwin":
logging.Log.Info().Msg("Running on macOS")
OS = MacOS
default:
// TODO: check if this will work on WSL, maybe it will?
logging.Log.Error().Msg("Unsupported operating system")
fmt.Fprint(SysConfig.ErrOut, "Unsupported operating system")
os.Exit(1)
}
}
Expand All @@ -66,26 +64,21 @@ func SetupOs() {
func SetupShell() {

ShellLocation = os.Getenv("SHELL")
logging.Log.Debug().Msgf("Trying to determine the shell: %s", ShellLocation)

shellType := path.Base(ShellLocation)

switch shellType {
case "bash":
logging.Log.Info().Msg("Running bash shell")
Shell = Bash
case "zsh":
logging.Log.Info().Msg("Running zsh shell")
Shell = Zsh
case "fish":
logging.Log.Info().Msg("Running fish shell")
Shell = Fish
case "sh":
logging.Log.Info().Msg("Running sh shell")
Shell = Sh
// TODO: consider supporting "ash" as well.
default:
logging.Log.Error().Msg("Unsupported shell")
fmt.Fprint(SysConfig.ErrOut, "Unsupported shell")
os.Exit(1)
}

Expand All @@ -95,7 +88,7 @@ func SetupShell() {
func SetupHomeDir() {
home, err := os.UserHomeDir()
if err != nil {
logging.Log.Error().Err(err).Msg("Failed to get user home directory")
fmt.Fprintf(SysConfig.ErrOut, "Failed to get user home directory: %s\n", err)
os.Exit(1)
}
HomeDir = home
Expand All @@ -106,7 +99,8 @@ func SetupLdaDir() {

dir := filepath.Join(HomeDir, ".lda")
if err := os.MkdirAll(dir, os.ModePerm); err != nil && !os.IsExist(err) {
logging.Log.Err(err).Msg("Failed to create shell configuration directory")
fmt.Fprintf(SysConfig.ErrOut, "Failed to create LDA home directory: %s\n", err)
os.Exit(1)
}

LdaDir = dir
Expand All @@ -121,7 +115,7 @@ func SetupUserConfig() {
func SetupLdaBinaryPath() {
exePath, err := os.Executable()
if err != nil {
logging.Log.Error().Err(err).Msg("Failed to get executable path")
fmt.Fprintf(SysConfig.ErrOut, "Failed to find executable path: %s\n", err)
os.Exit(1)
}
ExePath = exePath
Expand Down
4 changes: 2 additions & 2 deletions database/database.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package database

import (
"fmt"
"lda/config"
"lda/logging"
"os"
"path/filepath"

Expand All @@ -20,7 +20,7 @@ func Setup() {

db, err := sqlx.Connect("sqlite3", dbPath)
if err != nil {
logging.Log.Error().Err(err).Msg("Failed to setup database")
fmt.Fprintf(config.SysConfig.ErrOut, "Failed to setup database: %s\n", err)
os.Exit(1)
}
DB = db
Expand Down
Loading

0 comments on commit 8535b44

Please sign in to comment.