package options import ( "encoding/json" "flag" "fmt" "os" "rgdd.se/silent-ct/internal/manager" "rgdd.se/silent-ct/pkg/monitor" "rgdd.se/silent-ct/pkg/server" ) const usage = `Usage: silent-ct [Options] Options: -h, --help: Output usage message and exit -c, --config: Path to a configuration file (Default: %s) -l, --listen: Listen address to receive submission on (Default: %s) -s, --state: Path to a directory where state is stored (Default: %s) Example configuration file: { "monitor": [ { "wildcard": "example.org", "excludes": [ "test" ] } ], "nodes": [ { "name": "node_a", "secret": "aaaa", "issues": [ "example.org", "www.example.org" ] } ] } ` // Options are command-line options the user can specify type Options struct { ListenAddr string ConfigFile string StateDir string } func New(cmd string, args []string) (opts Options, err error) { fs := flag.NewFlagSet(cmd, flag.ContinueOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, usage, server.DefaultConfigFile, server.DefaultAddress, manager.DefaultStateDir) } stringOpt(fs, &opts.ConfigFile, "config", "c", server.DefaultConfigFile) stringOpt(fs, &opts.ListenAddr, "listen", "l", server.DefaultAddress) stringOpt(fs, &opts.StateDir, "state", "s", manager.DefaultStateDir) if err = fs.Parse(args); err != nil { return opts, err } if opts.ConfigFile == "" { return opts, fmt.Errorf("-c, --config: must not be an empty string") } if opts.StateDir == "" { return opts, fmt.Errorf("-s, --state: must not be an empty string") } if opts.ListenAddr == "" { return opts, fmt.Errorf("-l, --listen: must not be an empty string") } return opts, err } func stringOpt(fs *flag.FlagSet, opt *string, short, long, value string) { fs.StringVar(opt, short, value, "") fs.StringVar(opt, long, value, "") } type Config struct { Monitor monitor.MatchWildcards `json:"monitor"` Nodes server.Nodes `json:"nodes"` } func (c *Config) FromFile(fileName string) error { b, err := os.ReadFile(fileName) if err != nil { return err } return json.Unmarshal(b, c) }