From b000c45cff4fac2b51f778a520841c8a23b71f50 Mon Sep 17 00:00:00 2001 From: Alexander Staubo Date: Tue, 7 Feb 2023 11:52:18 +0100 Subject: [PATCH] feat: adds configuration file support. --- README.md | 15 +++++++++++++++ config.go | 43 +++++++++++++++++++++++++++++++++++++++++++ main.go | 48 ++++++++++++++++++++++++++++-------------------- 3 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 config.go diff --git a/README.md b/README.md index 00d085f..86585bf 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,21 @@ To abort tailing, hit `Ctrl+C`. Run `ktail -h` for usage. +## Configuration + +Ktail will read the file `$HOME/.config/ktail/config.yml` if it exists. This must be a file in YAML format. The following options can be set (these are the defaults): + +```yaml +noColor: false +raw: false +timestamps: false +quiet: false +colorScheme: bw +colorMode: auto +kubeConfigPath: "" +templateString: "" +``` + ## Templating ktail has a basic output format. To override, you can use a simple Go template. For example: diff --git a/config.go b/config.go new file mode 100644 index 0000000..b88b92f --- /dev/null +++ b/config.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + + "k8s.io/apimachinery/pkg/util/yaml" +) + +type Config struct { + Quiet bool `yaml:"quiet"` + NoColor bool `yaml:"noColor"` + Raw bool `yaml:"raw"` + Timestamps bool `yaml:"timestamps"` + ColorMode string `yaml:"colorMode"` + ColorScheme string `yaml:"colorScheme"` + TemplateString string `yaml:"templateString"` + KubeConfigPath string `yaml:"kubeConfigPath"` +} + +func (c *Config) LoadDefault() error { + home := os.Getenv("HOME") + if home == "" { + return nil + } + if err := c.LoadFromPath(filepath.Join(home, ".config", "ktail", "config.yml")); err != nil && + !os.IsNotExist(err) { + return err + } + return nil +} + +func (c *Config) LoadFromPath(path string) error { + data, err := os.ReadFile(path) + if err != nil { + return err + } + if err := yaml.UnmarshalStrict(data, c); err != nil { + return fmt.Errorf("parsing config file %q: %w", path, err) + } + return nil +} diff --git a/main.go b/main.go index fbdc8a5..1d9162f 100644 --- a/main.go +++ b/main.go @@ -25,17 +25,21 @@ import ( "k8s.io/klog/v2" ) -const defaultColorScheme = "bw" - func main() { klog.SetLogger(logr.New(&kubeLogger{})) + cfg := Config{ + ColorMode: "auto", + ColorScheme: "bw", + } + var ( - contextName string + contextName string + labelSelectorExpr string + namespaces []string + allNamespaces bool + kubeconfigPath string - labelSelectorExpr string - namespaces []string - allNamespaces bool quiet bool timestamps bool raw bool @@ -49,6 +53,10 @@ func main() { colorScheme string ) + if err := cfg.LoadDefault(); err != nil { + fail(err.Error()) + } + flags := pflag.NewFlagSet("ktail", pflag.ContinueOnError) flags.SortFlags = false flags.Usage = func() { @@ -56,8 +64,6 @@ func main() { flags.PrintDefaults() } flags.StringVar(&contextName, "context", "", "Kubernetes context name") - flags.StringVar(&kubeconfigPath, "kubeconfig", "", - "Path to kubeconfig (only required out-of-cluster)") flags.StringArrayVarP(&namespaces, "namespace", "n", []string{}, "Kubernetes namespace") flags.BoolVar(&allNamespaces, "all-namespaces", false, "Apply to all Kubernetes namespaces") flags.StringArrayVarP(&excludePatternStrings, "exclude", "x", []string{}, @@ -65,20 +71,23 @@ func main() { " include patterns and labels.") flags.StringVarP(&labelSelectorExpr, "selector", "l", "", "Match pods by label (see 'kubectl get -h' for syntax).") - flags.StringVarP(&tmplString, "template", "t", "", - "Template to format each line. For example, for"+ - " just the message, use --template '{{ .Message }}'.") - flags.BoolVarP(&raw, "raw", "r", false, "Don't format output; output messages only (unless --timestamps)") - flags.BoolVarP(×tamps, "timestamps", "T", false, "Include timestamps on each line") - flags.BoolVarP(&quiet, "quiet", "q", false, "Don't print events about new/deleted pods") flags.BoolVarP(&sinceStart, "since-start", "s", false, "Start reading log from the beginning of the container's lifetime.") flags.BoolVarP(&showVersion, "version", "", false, "Show version.") - flags.BoolVar(&noColor, "no-color", false, "Alias for --color=never.") - flags.StringVar(&colorMode, "color", "auto", "Set color mode: one of 'auto' (default), 'never', or 'always'. (Aliased as --colour.)") - flags.StringVar(&colorMode, "colour", "auto", "Set color mode: one of 'auto' (default), 'never', or 'always'.") - flags.StringVar(&colorScheme, "color-scheme", defaultColorScheme, "Set color scheme (see https://github.com/alecthomas/chroma/tree/master/styles). (Aliased as --colour-scheme.)") - flags.StringVar(&colorScheme, "colour-scheme", defaultColorScheme, "Set color scheme (see https://github.com/alecthomas/chroma/tree/master/styles).") + + flags.StringVar(&kubeconfigPath, "kubeconfig", cfg.KubeConfigPath, + "Path to kubeconfig (only required out-of-cluster)") + flags.StringVarP(&tmplString, "template", "t", cfg.TemplateString, + "Template to format each line. For example, for"+ + " just the message, use --template '{{ .Message }}'.") + flags.BoolVarP(&raw, "raw", "r", cfg.Raw, "Don't format output; output messages only (unless --timestamps)") + flags.BoolVarP(×tamps, "timestamps", "T", cfg.Timestamps, "Include timestamps on each line") + flags.BoolVarP(&quiet, "quiet", "q", cfg.Quiet, "Don't print events about new/deleted pods") + flags.BoolVar(&noColor, "no-color", cfg.NoColor, "Alias for --color=never.") + flags.StringVar(&colorMode, "color", cfg.ColorMode, "Set color mode: one of 'auto' (default), 'never', or 'always'. (Aliased as --colour.)") + flags.StringVar(&colorMode, "colour", cfg.ColorMode, "Set color mode: one of 'auto' (default), 'never', or 'always'.") + flags.StringVar(&colorScheme, "color-scheme", cfg.ColorScheme, "Set color scheme (see https://github.com/alecthomas/chroma/tree/master/styles). (Aliased as --colour-scheme.)") + flags.StringVar(&colorScheme, "colour-scheme", cfg.ColorScheme, "Set color scheme (see https://github.com/alecthomas/chroma/tree/master/styles).") _ = flags.MarkHidden("colour") _ = flags.MarkHidden("colour-scheme") @@ -87,7 +96,6 @@ func main() { os.Exit(2) } fail(err.Error()) - os.Exit(1) } if noColor {