0

I am trying to create a simple cli tool in Go using a TOML config file. I want to be able to store frequent commands I use on the command line for other tools, in a TOML file and use my CLI program to recall those. I want to make adding a new tool / command to the TOML file as easy as possible for other users. The trouble I am having is getting Go to recognize a new tool added to the TOML config file, without manually opening my config.go file and adding the tool to the config struct that is holding the parsed TOML data. Example TOML config:

# Configuration File
#
[assetfinder]
default = "assetfinder -subs-only {{TARGET}}"
silent = "assetfinder -subs-only {{TARGET}} --silent"

[subfinder]
default = "subfinder -u {{TARGET}}"
silent = "subfinder -u {{TARGET}} --silent"

I want a user to be able to add another tool/command without having to touch the source code and manually add it to the struct. Here is config.go:

package config

import (
    "github.com/spf13/viper"
)

type Config struct {
    Assetfinder map[string]string
    Subfinder map[string]string
}

func Load() (*Config, error) {
    v := viper.New()
    v.SetConfigName("config")
    v.AddConfigPath(".")
    err := v.ReadInConfig()
    if err != nil {
        return nil, err
    }
    c := &Config{}
    err = v.Unmarshal(c)
    return c, err
}
DS82
  • 1
  • 1

1 Answers1

0

The viper has a solution about "Watching and re-reading config files". https://github.com/spf13/viper#watching-and-re-reading-config-files.

You just need to register to OnConfigChange event and call WatchConfig:

err := v.ReadInConfig()
if err != nil {
    return nil, err
}
viper.OnConfigChange(func(e fsnotify.Event) {
    fmt.Println("Config file changed:", e.Name)
    // TODO: read config from viper and update you logic
})
viper.WatchConfig()

The WatchConfig implements is in https://github.com/spf13/viper/blob/master/viper.go#L431

  1. it use fsnotify to watch file change
  2. when file create/write, it call ReadInConfig to update
  3. trigger onConfigChange event
Xianzhi Xia
  • 146
  • 2
  • Thank you so much for your response Xianzhi! I am wondering if it may just be the way I am writing out my struct or possibly even the TOML file. I don't know that I need the application to monitor for config changes while it is running. The purpose of the tool I am trying to write is essentially just a library or index of bash commands. For more context, I am a web security tester so I run a lot of different tools from the CLI. – DS82 May 13 '22 at 03:35
  • I want a tool that I can store all the different command / flag strings in so that I do not have to constantly refer to each tool's help menu to remember what specific flags to run. I just want to store the commands in a config file for each tool, and then use my tool to select and run those commands. So I guess what I really need is a struct that will hold all the tools / commands but not have to add a field in the struct for each new tool I add to the config.. if that's possible – DS82 May 13 '22 at 03:38
  • I think the `alias` command in bash can satisfy to you. https://stackoverflow.com/questions/8967843/how-do-i-create-a-bash-alias. https://stackoverflow.com/questions/7131670/make-a-bash-alias-that-takes-a-parameter/7131683#7131683 – Xianzhi Xia May 13 '22 at 04:37
  • But if you want to write a self-customized cli tool with golang, you can iterate viper.AllKeys(), and then viper.GetStringMapString. – Xianzhi Xia May 13 '22 at 04:53