Skip to content

Commit

Permalink
still prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
tbauriedel committed Jul 4, 2024
1 parent 5f2adae commit d0a6164
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 88 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/mod v0.16.0 // indirect
github.com/spf13/cobra v1.8.1 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/tools v0.19.0 // indirect
)
11 changes: 6 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
github.com/Showmax/go-fqdn v1.0.0 h1:0rG5IbmVliNT5O19Mfuvna9LL7zlHyRfsSvBPZmF9tM=
github.com/Showmax/go-fqdn v1.0.0/go.mod h1:SfrFBzmDCtCGrnHhoDjuvFnKsWjEQX/Q9ARZvOrJAko=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
Expand All @@ -11,23 +14,21 @@ github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
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/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
106 changes: 93 additions & 13 deletions internal/arguments/arguments.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,120 @@ package arguments
import (
"bufio"
"fmt"
flag "github.com/spf13/pflag"
"os"
"strings"
)

func NewStringVar(callback *string, value string, usage string) {
scanner := bufio.NewScanner(os.Stdin)
var (
NonInteractive bool
validBooleanInputs = map[string]bool{
"y": true,
"yes": true,
"n": false,
"no": false,
}
)

type Handler struct {
scanner *bufio.Scanner
prompts []func()
}

func NewHandler() Handler {
return Handler{
scanner: bufio.NewScanner(os.Stdin),
}
}

func (h *Handler) ReadArgumentsFromStdin() {
for _, prompt := range h.prompts {
prompt()
}
}

func (h *Handler) NewPromptStringVar(callback *string, name, defaultValue, usage string, required bool) {
flag.StringVar(callback, name, defaultValue, usage)

h.prompts = append(h.prompts, func() {
if *callback != "" {
defaultValue = *callback
}

h.newStringPrompt(callback, defaultValue, usage, required)
})
}

func (h *Handler) NewPromptStringSliceVar(callback *[]string, name string, defaultValue []string, usage string, required bool) {
flag.StringSliceVar(callback, name, defaultValue, usage)

h.prompts = append(h.prompts, func() {
if len(*callback) > 0 {
defaultValue = *callback
}

var input string

h.newStringPrompt(&input, strings.Join(defaultValue, ","), usage, required)
*callback = strings.Split(input, ",")
})
}

func (h *Handler) NewPromptBoolVar(callback *bool, name string, defaultValue bool, usage string) {
flag.BoolVar(callback, name, defaultValue, usage)

h.prompts = append(h.prompts, func() {
h.newBoolPrompt(callback, defaultValue, usage)
})
}

func (h *Handler) newStringPrompt(callback *string, defaultValue, usage string, required bool) {
for {
fmt.Printf("%s - (Default: %s): ", usage, value)
if scanner.Scan() {
input := scanner.Text()
fmt.Printf("%s - (Preselection: '%s'): ", usage, defaultValue)
if h.scanner.Scan() {
input := h.scanner.Text()
if input != "" {
*callback = input
break
} else {
*callback = value
} else if input == "" && defaultValue != "" {
*callback = defaultValue
break
} else if input == "" && !required {
break
}
} else {
if err := scanner.Err(); err != nil {
if err := h.scanner.Err(); err != nil {
_, _ = fmt.Fprintln(os.Stderr, "reading standard input:", err)
break
}
}
}

return
}

func NewStringSliceVar(callback *[]string, value []string, usage string) {
var input string
NewStringVar(&input, strings.Join(value, ","), usage)
func (h *Handler) newBoolPrompt(callback *bool, defaultValue bool, usage string) {
for {
fmt.Printf("%s [y/n] - (Preselection: '%t'): ", usage, defaultValue)

if h.scanner.Scan() {
input := strings.ToLower(h.scanner.Text())

*callback = strings.Split(input, ",")
if input != "" && isValidBoolString(input) {
*callback = validBooleanInputs[input]
break
} else if input == "" {
*callback = defaultValue
break
}
}
}
}

func NewBoolVar() {
func isValidBoolString(input string) bool {
if _, ok := validBooleanInputs[input]; !ok {
return false
}

return true
}
140 changes: 72 additions & 68 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"github.com/NETWAYS/support-collector/internal/arguments"
"github.com/NETWAYS/support-collector/internal/metrics"
flag "github.com/spf13/pflag"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -36,16 +37,15 @@ import (

"github.com/mattn/go-colorable"
"github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
)

const Product = "NETWAYS support collector"
const Product = "NETWAYS support-collector"

// FilePrefix for the outfile file.
const FilePrefix = "netways-support"
const FilePrefix = "support-collector"

const Readme = `
The support collector allows our customers to collect relevant information from
The support-collector allows our customers to collect relevant information from
their servers. A resulting ZIP file can then be provided to our support team
for further inspection.
Expand Down Expand Up @@ -108,22 +108,79 @@ var (
)

var (
verbose, printVersion bool
enabledModules, disabledModules []string
extraObfuscators []string
outputFile string
commandTimeout = 60 * time.Second
noDetailedCollection bool
startTime = time.Now()
metric *metrics.Metrics
verbose, printVersion, noDetailedCollection bool
enabledModules, disabledModules, extraObfuscators []string
outputFile string
commandTimeout = 60 * time.Second
startTime = time.Now()
metric *metrics.Metrics
)

func main() {
handleArguments()

func init() {
// Set locale to C, to avoid translations in command output
_ = os.Setenv("LANG", "C")

args := arguments.NewHandler()

// General arguments without interactive prompt
flag.BoolVar(&arguments.NonInteractive, "nonInteractive", false, "Enable non-interactive mode")
flag.BoolVar(&printVersion, "version", false, "Print version and exit")
flag.BoolVar(&verbose, "verbose", false, "Enable verbose logging")

// TODO
//flag.DurationVar(&commandTimeout, "command-timeout", commandTimeout, "Timeout for command execution in modules")

// Run specific arguments
args.NewPromptStringVar(&outputFile, "output", buildFileName(), "Output file for the ZIP content", true)
args.NewPromptStringSliceVar(&enabledModules, "enable", moduleOrder, "Comma separated list of enabled modules", false)
args.NewPromptStringSliceVar(&disabledModules, "disable", []string{}, "Comma separated list of disabled modules", false)
args.NewPromptBoolVar(&noDetailedCollection, "nodetails", false, "Disable detailed collection including logs and more")

// Icinga 2 specific arguments
args.NewPromptStringVar(&icinga2.APICred.Username, "icinga2-api-user", "", "Username of global Icinga 2 API user to collect data about Icinga 2 Infrastructure", false)
args.NewPromptStringVar(&icinga2.APICred.Password, "icinga2-api-pass", "", "Password for global Icinga 2 API user to collect data about Icinga 2 Infrastructure", false)
args.NewPromptStringSliceVar(&icinga2.APIEndpoints, "icinga2-api-endpoints", []string{}, "Comma separated list of Icinga 2 API Endpoints (including port) to collect data from. FQDN or IP address must be reachable. (Example: i2-master01.local:5665)", false)

flag.CommandLine.SortFlags = false

// Output a proper help message with details
flag.Usage = func() {
_, _ = fmt.Fprintf(os.Stderr, "%s\n\n%s\n\n", Product, strings.Trim(Readme, "\n"))

_, _ = fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])

flag.PrintDefaults()
}

flag.Parse()

if printVersion {
fmt.Println(Product, "version", getBuildInfo()) //nolint:forbidigo
os.Exit(0)
}

if !arguments.NonInteractive {
args.ReadArgumentsFromStdin()
}

// Verify enabled modules
for _, name := range enabledModules {
if _, ok := modules[name]; !ok {
logrus.Fatal("Unknown module to enable: ", name)
}
}

fmt.Println(noDetailedCollection)

os.Exit(1)
}

// buildFileName returns a filename to store the output of support collector.
func buildFileName() string {
return FilePrefix + "_" + util.GetHostnameWithoutDomain() + "_" + time.Now().Format("20060102-1504") + ".zip"
}

func main() {
c, closeCollection := NewCollection(outputFile)
// Close collection
defer closeCollection()
Expand Down Expand Up @@ -184,59 +241,6 @@ func main() {
c.Log.Infof("Generated ZIP file located at %s", path)
}

func handleArguments() {
// TODO only a prototype
arguments.NewStringVar(&outputFile, buildFileName(), "Output file for the ZIP content")
arguments.NewStringSliceVar(&enabledModules, moduleOrder, "Comma seperated list of enabled module")

// arguments for collection handling
//flag.StringSliceVar(&enabledModules, "enable", moduleOrder, "List of enabled module")
flag.StringSliceVar(&disabledModules, "disable", []string{}, "List of disabled module")
//flag.StringVarP(&outputFile, "output", "o", buildFileName(), "Output file for the ZIP content")
flag.BoolVar(&noDetailedCollection, "nodetails", false, "Disable detailed collection including logs and more")
flag.StringArrayVar(&extraObfuscators, "hide", []string{}, "List of additional strings to obfuscate. Can be used multiple times and supports regex.") //nolint:lll
flag.DurationVar(&commandTimeout, "command-timeout", commandTimeout, "Timeout for command execution in modules")

// api credentials for icinga 2 modules
flag.StringVar(&icinga2.APICred.Username, "icinga2-api-user", "", "Username of global Icinga 2 API user to collect data about Icinga 2 Infrastructure") //nolint:lll
flag.StringVar(&icinga2.APICred.Password, "icinga2-api-pass", "", "Password for global Icinga 2 API user to collect data about Icinga 2 Infrastructure") //nolint:lll
flag.StringSliceVar(&icinga2.APIEndpoints, "icinga2-api-endpoints", []string{}, "List of Icinga 2 API Endpoints (including port) to collect data from. FQDN or IP address must be reachable. (Example: i2-master01.local:5665)") //nolint:lll

// basic arguments
flag.BoolVarP(&printVersion, "version", "V", false, "Print version and exit")
flag.BoolVarP(&verbose, "verbose", "v", false, "Enable verbose logging")

flag.CommandLine.SortFlags = false

// Output a proper help message with details
flag.Usage = func() {
_, _ = fmt.Fprintf(os.Stderr, "%s\n\n%s\n\n", Product, strings.Trim(Readme, "\n"))

_, _ = fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])

flag.PrintDefaults()
}

flag.Parse()

if printVersion {
fmt.Println(Product, "version", getBuildInfo()) //nolint:forbidigo
os.Exit(0)
}

// Verify enabled modules
for _, name := range enabledModules {
if _, ok := modules[name]; !ok {
logrus.Fatal("Unknown module to enable: ", name)
}
}
}

// buildFileName returns a filename to store the output of support collector.
func buildFileName() string {
return util.GetHostnameWithoutDomain() + "-" + FilePrefix + "-" + time.Now().Format("20060102-1504") + ".zip"
}

// NewCollection starts a new collection. outputFile will be created.
//
// Collection and cleanup function to defer are returned
Expand Down

0 comments on commit d0a6164

Please sign in to comment.