Skip to content

Commit

Permalink
Use the cobra package for command-line argument parsing. (#9)
Browse files Browse the repository at this point in the history
* Add package 'cobra'
* Implement cobra argument parsing and move logic from main() to cmd.Execute()

---------

Co-authored-by: Abhisheke Acharya <abh1sheke.acharya@gmail.com>
  • Loading branch information
Abhisheke Acharya and Abhisheke Acharya authored Dec 31, 2023
1 parent c8973e5 commit 1973eba
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 135 deletions.
18 changes: 9 additions & 9 deletions main_test.go → cmd/cmd_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package cmd

import (
"os"
Expand All @@ -11,8 +11,8 @@ import (
func TestResolveFile(t *testing.T) {
os.Stdout, _ = os.Open(os.DevNull)
defer os.Stdout.Close()
logFile, _ := logs.LoadLogFile("./examples/apt-term.log")
configuration, _ := config.CreateConfiguration("./examples/apt-term-config.json")
logFile, _ := logs.LoadLogFile("../examples/apt-term.log")
configuration, _ := config.CreateConfiguration("../examples/apt-term-config.json")

_, err := resolveLogFile(logFile, configuration)

Expand All @@ -25,8 +25,8 @@ func TestResolveLogFileBadLog(t *testing.T) {
os.Stdout, _ = os.Open(os.DevNull)
defer os.Stdout.Close()

logFile, _ := logs.LoadLogFile("./examples/apt-term-bad.log")
configuration, _ := config.CreateConfiguration("./examples/apt-term-config.json")
logFile, _ := logs.LoadLogFile("../examples/apt-term-bad.log")
configuration, _ := config.CreateConfiguration("../examples/apt-term-config.json")

_, err := resolveLogFile(logFile, configuration)

Expand All @@ -39,8 +39,8 @@ func TestResolveLogFileBadConfig(t *testing.T) {
os.Stdout, _ = os.Open(os.DevNull)
defer os.Stdout.Close()

logFile, _ := logs.LoadLogFile("./examples/apt-term.log")
configuration, _ := config.CreateConfiguration("./examples/apt-term-config-bad.json")
logFile, _ := logs.LoadLogFile("../examples/apt-term.log")
configuration, _ := config.CreateConfiguration("../examples/apt-term-config-bad.json")

_, err := resolveLogFile(logFile, configuration)

Expand All @@ -50,7 +50,7 @@ func TestResolveLogFileBadConfig(t *testing.T) {
}

func TestResolveLogFileNoConfigName(t *testing.T) {
logFile, _ := logs.LoadLogFile("./examples/apt-term.log")
logFile, _ := logs.LoadLogFile("../examples/apt-term.log")
configuration := &config.Configuration{
Rules: make([]config.Rule, 1),
}
Expand All @@ -63,7 +63,7 @@ func TestResolveLogFileNoConfigName(t *testing.T) {
}

func TestResolveLogFileNoConfigRules(t *testing.T) {
logFile, _ := logs.LoadLogFile("./examples/apt-term.log")
logFile, _ := logs.LoadLogFile("../examples/apt-term.log")
configuration := &config.Configuration{
Name: "test",
}
Expand Down
125 changes: 125 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package cmd

import (
"fmt"
"os"

config "github.com/kyallanum/athena/v1.0.0/models/config"
library "github.com/kyallanum/athena/v1.0.0/models/library"
logs "github.com/kyallanum/athena/v1.0.0/models/logs"
"github.com/spf13/cobra"
)

var configFile, logFile string

var rootCmd = &cobra.Command{
Use: "athena [flags]",
Short: "A text and log file parser to discern important information",
SilenceUsage: true,
SilenceErrors: true,
RunE: func(cmd *cobra.Command, args []string) error {
if len(configFile) == 0 {
return fmt.Errorf(`required flag(s) "config" not set`)
}
if len(logFile) == 0 {
return fmt.Errorf(`required flag(s) "log-file" not set`)
}
return nil
},
}

func Execute() error {
errCheck := func(err error) {
if err != nil {
panic(err)
}
}

err := rootCmd.Execute()
errCheck(err)
fmt.Println("Athena v1.0.0 Starting")

fmt.Println("Getting Configuration File: ", configFile, "...")
configuration, err := config.CreateConfiguration(configFile)
errCheck(err)
fmt.Println("Configuration Loaded")

fmt.Println("Loading Log File: ", logFile, "... ")
logFileContents, err := logs.LoadLogFile(logFile)
errCheck(err)
fmt.Println("Log File Loaded")

library, err := resolveLogFile(logFileContents, configuration)
errCheck(err)

err = printSummary(library)
errCheck(err)

return nil
}

func init() {
rootCmd.Flags().StringVarP(&configFile, "config", "c", os.Getenv(""), "")
rootCmd.Flags().StringVarP(&logFile, "log-file", "l", os.Getenv(""), "")
}

func resolveLogFile(contents *logs.LogFile, configuration *config.Configuration) (*library.Library, error) {
wrapError := func(err error) error {
return fmt.Errorf("unable to resolve log file: \n\t%w", err)
}

if contents == nil || contents.Len() == 0 {
return nil, fmt.Errorf("log file contains no contents")
} else if configuration == nil || (configuration.Name == "" && configuration.Rules == nil) {
return nil, fmt.Errorf("configuration file has no contents")
} else if configuration.Name == "" {
return nil, fmt.Errorf("configuration file contains no log name")
} else if configuration.Rules == nil || len(configuration.Rules) == 0 {
return nil, fmt.Errorf("configuration does not have any rules")
}

ret_library := library.Library.New(library.Library{}, configuration.Name)

fmt.Println("Resolving Log File")
for i := 0; i < len(configuration.Rules); i++ {
currentRuleData, err := config.ResolveRule(contents, &configuration.Rules[i])
if err != nil {
return nil, wrapError(err)
}

ret_library.AddRuleData(configuration.Rules[i].Name, currentRuleData)
}

fmt.Println("Log File Resolved")

return ret_library, nil
}

func printSummary(library *library.Library) error {
wrapError := func(err error) error {
return fmt.Errorf("unable to print summary: \n\t%w", err)
}

libraryName, err := library.Name()
if err != nil {
return wrapError(err)
}

fmt.Printf("\n--------------- %s Log File Summary ---------------\n", libraryName)
libraryKeys := library.LibraryKeys()
for _, rule := range libraryKeys {
fmt.Printf("Rule: %s\n", rule)
ruleData, _ := library.RuleData(rule)
summaryDataLen := ruleData.SummaryDataLen()
if summaryDataLen == 0 {
fmt.Println("No summary lines provided.")
} else {
for i := 0; i < summaryDataLen; i++ {
fmt.Println("\t", ruleData.SummaryData(i))
}
}
fmt.Println()
}

return nil
}
7 changes: 6 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ go 1.21

require github.com/davidmytton/url-verifier v1.0.0

require github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidmytton/url-verifier v1.0.0 h1:TIdwZ+rWVnfnJPMD/DclwEJ0XewV4jkr0qEcX/58n+4=
github.com/davidmytton/url-verifier v1.0.0/go.mod h1:8mPy8FL7r56f0WpwZm9+PvPwc3i1lX4eKaF8mosx4WE=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
130 changes: 5 additions & 125 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,140 +1,20 @@
package main

import (
"flag"
"fmt"
"log"
"os"

config "github.com/kyallanum/athena/v1.0.0/models/config"
library "github.com/kyallanum/athena/v1.0.0/models/library"
logs "github.com/kyallanum/athena/v1.0.0/models/logs"
"github.com/kyallanum/athena/v1.0.0/cmd"
)

func errCheck(err error) {
if err != nil {
panic(err)
}
}

func parseFlags(configFile *string, logFile *string) error {
var configFlag string
var logFlag string

flag.StringVar(&configFlag, "c", "", "")
flag.StringVar(&configFlag, "config", "", "")
flag.StringVar(&logFlag, "l", "", "")
flag.StringVar(&logFlag, "log-file", "", "")
flag.Parse()

if *configFile == "" {
*configFile = configFlag
}
if *logFile == "" {
*logFile = logFlag
}

if *configFile == "" {
return fmt.Errorf("configuration file was not specified")
}

if *logFile == "" {
return fmt.Errorf("log file was not specified")
}

return nil
}

func resolveLogFile(contents *logs.LogFile, configuration *config.Configuration) (*library.Library, error) {
wrapError := func(err error) error {
return fmt.Errorf("unable to resolve log file: \n\t%w", err)
}

if contents == nil || contents.Len() == 0 {
return nil, fmt.Errorf("log file contains no contents")
} else if configuration == nil || (configuration.Name == "" && configuration.Rules == nil) {
return nil, fmt.Errorf("configuration file has no contents")
} else if configuration.Name == "" {
return nil, fmt.Errorf("configuration file contains no log name")
} else if configuration.Rules == nil || len(configuration.Rules) == 0 {
return nil, fmt.Errorf("configuration does not have any rules")
}

ret_library := library.Library.New(library.Library{}, configuration.Name)

fmt.Println("Resolving Log File")
for i := 0; i < len(configuration.Rules); i++ {
currentRuleData, err := config.ResolveRule(contents, &configuration.Rules[i])
if err != nil {
return nil, wrapError(err)
}

ret_library.AddRuleData(configuration.Rules[i].Name, currentRuleData)
}

fmt.Println("Log File Resolved")

return ret_library, nil
}

func printSummary(library *library.Library) error {
wrapError := func(err error) error {
return fmt.Errorf("unable to print summary: \n\t%w", err)
}

libraryName, err := library.Name()
if err != nil {
return wrapError(err)
}

fmt.Printf("\n--------------- %s Log File Summary ---------------\n", libraryName)
libraryKeys := library.LibraryKeys()
for _, rule := range libraryKeys {
fmt.Printf("Rule: %s\n", rule)
ruleData, _ := library.RuleData(rule)
summaryDataLen := ruleData.SummaryDataLen()
if summaryDataLen == 0 {
fmt.Println("No summary lines provided.")
} else {
for i := 0; i < summaryDataLen; i++ {
fmt.Println("\t", ruleData.SummaryData(i))
}
}
fmt.Println()
}

return nil
}

func main() {
logger := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime)

defer func() {
if err := recover(); err != nil {
logger.Fatal("\nAn issue occurred:", err)
fmt.Fprintln(os.Stderr, "\nAn error occured: ", err)
}
}()

CONFIG_FILE := os.Getenv("ATHENA_CONFIG_FILE")
LOG_FILE := os.Getenv("ATHENA_LOG_FILE")

parseFlags(&CONFIG_FILE, &LOG_FILE)

logger.Print("Athena v1.0.0 Starting")

fmt.Println("Getting Configuration File: ", CONFIG_FILE, "...")
configuration, err := config.CreateConfiguration(CONFIG_FILE)
errCheck(err)
fmt.Println("Configuration Loaded")

fmt.Println("Loading Log File: ", LOG_FILE, "... ")
logFileContents, err := logs.LoadLogFile(LOG_FILE)
errCheck(err)
fmt.Println("Log File Loaded")

library, err := resolveLogFile(logFileContents, configuration)
errCheck(err)

err = printSummary(library)
errCheck(err)
if err := cmd.Execute(); err != nil {
panic(err)
}
}

0 comments on commit 1973eba

Please sign in to comment.