diff --git a/cmd/discuss.go b/cmd/discuss.go index da9d76f98..0d389be40 100644 --- a/cmd/discuss.go +++ b/cmd/discuss.go @@ -54,9 +54,9 @@ func runDiscuss(cmd *cobra.Command, args []string) { redacted = redact(string(src)) } - out := new(bytes.Buffer) tmpl := template.Must(template.New("discuss").Parse(discussTmpl)) + out := new(bytes.Buffer) _ = tmpl.Execute(out, map[string]any{ "CfgFile": file, "CfgError": errorString(cfgErr), diff --git a/cmd/dump.go b/cmd/dump.go index 9ff4391ae..d5443fea7 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -1,8 +1,14 @@ package cmd import ( + "bytes" + _ "embed" "fmt" + "os" + "path/filepath" + "text/template" + "github.com/Masterminds/sprig/v3" "github.com/evcc-io/evcc/core" "github.com/evcc-io/evcc/server" "github.com/evcc-io/evcc/util" @@ -17,8 +23,17 @@ var dumpCmd = &cobra.Command{ Run: runDump, } +var ( + //go:embed dump.tpl + dumpTmpl string + + dumpConfig *bool +) + func init() { rootCmd.AddCommand(dumpCmd) + + dumpConfig = dumpCmd.Flags().Bool("cfg", false, "Dump config file") } func handle(device any, err error) any { @@ -33,16 +48,47 @@ func runDump(cmd *cobra.Command, args []string) { log.INFO.Printf("evcc %s", server.FormattedVersion()) // load config - if err := loadConfigFile(&conf); err != nil { - log.FATAL.Fatal(err) - } + err := loadConfigFile(&conf) // setup environment - if err := configureEnvironment(conf); err != nil { - log.FATAL.Fatal(err) + if err == nil { + err = configureEnvironment(conf) + } + + var site *core.Site + if err == nil { + site, err = configureSiteAndLoadpoints(conf) + } + + if *dumpConfig { + file, pathErr := filepath.Abs(cfgFile) + if pathErr != nil { + file = cfgFile + } + + var redacted string + if src, err := os.ReadFile(cfgFile); err == nil { + redacted = redact(string(src)) + } + + tmpl := template.Must( + template.New("dump"). + Funcs(template.FuncMap(sprig.FuncMap())). + Parse(dumpTmpl)) + + out := new(bytes.Buffer) + _ = tmpl.Execute(out, map[string]any{ + "CfgFile": file, + "CfgError": errorString(err), + "CfgContent": redacted, + "Version": server.FormattedVersion(), + }) + + fmt.Println(out.String()) + + os.Exit(0) } - site, err := configureSiteAndLoadpoints(conf) if err != nil { log.FATAL.Fatal(err) } diff --git a/cmd/dump.tpl b/cmd/dump.tpl new file mode 100644 index 000000000..74ce096d5 --- /dev/null +++ b/cmd/dump.tpl @@ -0,0 +1,18 @@ + +{{ if .CfgError -}} +Fehlermeldung: + +{{ .CfgError | indent 4 }} + +{{ end -}} + +{{ if .CfgContent -}} +Konfiguration{{ if .CfgFile }} ({{ .CfgFile }}){{ end }}: + +{{ .CfgContent }} + +{{ end -}} + +{{ if .Version -}} +Version: `{{ .Version }}` +{{ end -}} diff --git a/cmd/flags.go b/cmd/flags.go index 46341c711..453d56a64 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/spf13/viper" ) const ( @@ -32,6 +33,18 @@ const ( flagDelay = "delay" ) +func bind(cmd *cobra.Command, flag, vpr string) { + if err := viper.BindPFlag(vpr, cmd.Flags().Lookup(flag)); err != nil { + panic(err) + } +} + +func bindP(cmd *cobra.Command, flag, vpr string) { + if err := viper.BindPFlag(vpr, cmd.PersistentFlags().Lookup(flag)); err != nil { + panic(err) + } +} + func selectByName(cmd *cobra.Command, conf *[]qualifiedConfig) error { flag := cmd.PersistentFlags().Lookup(flagName) if !flag.Changed { diff --git a/cmd/root.go b/cmd/root.go index 695cac71e..f7b73fc4c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -51,54 +51,28 @@ var rootCmd = &cobra.Command{ Use: "evcc", Short: "EV Charge Controller", Version: server.FormattedVersion(), - Run: run, -} - -func bind(cmd *cobra.Command, flag string) { - if err := viper.BindPFlag(flag, cmd.PersistentFlags().Lookup(flag)); err != nil { - panic(err) - } -} - -func configureCommand(cmd *cobra.Command) { - cmd.PersistentFlags().StringP( - "log", "l", - "info", - "Log level (fatal, error, warn, info, debug, trace)", - ) - bind(cmd, "log") - - cmd.PersistentFlags().StringVarP(&cfgFile, - "config", "c", - "", - "Config file (default \"~/evcc.yaml\" or \"/etc/evcc.yaml\")", - ) - cmd.PersistentFlags().BoolP( - "help", "h", - false, - "Help for "+cmd.Name(), - ) + Run: runRoot, } func init() { cobra.OnInitialize(initConfig) - configureCommand(rootCmd) - rootCmd.PersistentFlags().IntP("port", "p", 7070, "Listen port") - if err := viper.BindPFlag("network.port", rootCmd.PersistentFlags().Lookup("port")); err != nil { - panic(err) - } + // global options + rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file (default \"~/evcc.yaml\" or \"/etc/evcc.yaml\")") - rootCmd.PersistentFlags().DurationP("interval", "i", 10*time.Second, "Update interval") - bind(rootCmd, "interval") - - rootCmd.PersistentFlags().Bool("metrics", false, "Expose metrics") - bind(rootCmd, "metrics") - - rootCmd.PersistentFlags().Bool("profile", false, "Expose pprof profiles") - bind(rootCmd, "profile") + rootCmd.PersistentFlags().BoolP("help", "h", false, "Help") rootCmd.PersistentFlags().Bool(flagHeaders, false, flagHeadersDescription) + + // config file options + rootCmd.PersistentFlags().StringP("log", "l", "info", "Log level (fatal, error, warn, info, debug, trace)") + bindP(rootCmd, "log", "log") + + rootCmd.Flags().Bool("metrics", false, "Expose metrics") + bind(rootCmd, "metrics", "metrics") + + rootCmd.Flags().Bool("profile", false, "Expose pprof profiles") + bind(rootCmd, "profile", "profile") } // initConfig reads in config file and ENV variables if set @@ -189,7 +163,7 @@ func publishErrorInfo(cfgFile string, err error) { publish("fatal", unwrap(err)) } -func run(cmd *cobra.Command, args []string) { +func runRoot(cmd *cobra.Command, args []string) { util.LogLevel(viper.GetString("log"), viper.GetStringMapString("levels")) log.INFO.Printf("evcc %s", server.FormattedVersion())