kelseyhightower / envconfig

Golang library for managing configuration data from environment variables
MIT License
5.01k stars 377 forks source link

Feature Request: Make usage available in machine processable format #205

Open neumantm opened 2 years ago

neumantm commented 2 years ago

Feature

This goes into a very similar direction as #97. I would like to be able to get the usage info in form that can easily be processes by other parts of my program.

Reasons

I think it is a good idea to give developers more control how to inform the user about usage information. I can think of the following scenarios that currently are hard to implement:

Workaround

Currently I use a template which outputs the usage information as JSON, which can then be parsed again. But this is a really hacky solution requiring additional code, which would be unnecessary if envconfig had a way to get this info directly.

For anyone who might have a similar problem: Here is my code to do that:

// Variable describes one possible environment variable
type Variable struct {
    Name        string `json:"name"`
    Type        string `json:"type"`
    Default     string `json:"default"`
    Required    bool   `json:"required"`
    Description string `json:"description"`
}

// usageFormat is used by getUsage to print the usage info from envconfig as a json
const usageFormat = `{{ define "dec" }}{{ len (slice (printf "%*s" . "") 1) }}{{ end -}}
{{$length := len . -}}
[
{{range $idx, $val := .}}  {
    "name": "{{usage_key $val}}",
    "type": "{{usage_type $val}}",
    "default": "{{usage_default $val}}",
    "required": {{if usage_required $val -}} true {{- else -}} false {{- end}},
    "description": "{{usage_description $val}}"
  }{{if not (eq $idx (len (slice (printf "%*s" $length "") 1)))}},{{end}}{{/* If not last element print comma */}}
{{end}}]
`

// getUsage gets the usage information from envconfig, parses it and returns it as a array of Variables
func getUsage(config interface{}) ([]Variable, error) {
    var buff bytes.Buffer
    var vars []Variable

    if err := envconfig.Usagef(PREFIX, config, io.Writer(&buff), usageFormat); err != nil {
        return vars, errors.New(err)
    }

    if err := json.Unmarshal(buff.Bytes(), &vars); err != nil {
        return vars, errors.New(err)
    }

    return vars, nil
}