We also need to upgrade the linter together with the Go version, all the changes should relate to either fixing linting problems or upgrading the Go version used to build Grafana.
150 lines
3.0 KiB
Go
150 lines
3.0 KiB
Go
package setting
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil" //nolint:staticcheck // No need to change in v8.
|
|
"os"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
|
|
"gopkg.in/ini.v1"
|
|
)
|
|
|
|
type Expander interface {
|
|
SetupExpander(file *ini.File) error
|
|
Expand(string) (string, error)
|
|
}
|
|
|
|
type registeredExpander struct {
|
|
name string
|
|
priority int64
|
|
expander Expander
|
|
}
|
|
|
|
var expanders = []registeredExpander{
|
|
{
|
|
name: "env",
|
|
priority: -10,
|
|
expander: envExpander{},
|
|
},
|
|
{
|
|
name: "file",
|
|
priority: -5,
|
|
expander: fileExpander{},
|
|
},
|
|
}
|
|
|
|
func AddExpander(name string, priority int64, e Expander) {
|
|
expanders = append(expanders, registeredExpander{
|
|
name: name,
|
|
priority: priority,
|
|
expander: e,
|
|
})
|
|
}
|
|
|
|
var regex = regexp.MustCompile(`\$(|__\w+){([^}]+)}`)
|
|
|
|
func expandConfig(file *ini.File) error {
|
|
sort.Slice(expanders, func(i, j int) bool {
|
|
return expanders[i].priority < expanders[j].priority
|
|
})
|
|
|
|
for _, expander := range expanders {
|
|
err := expander.expander.SetupExpander(file)
|
|
if err != nil {
|
|
return fmt.Errorf("got error during initilazation of expander '%s': %w", expander.name, err)
|
|
}
|
|
|
|
for _, section := range file.Sections() {
|
|
for _, key := range section.Keys() {
|
|
updated, err := applyExpander(key.Value(), expander)
|
|
if err != nil {
|
|
return fmt.Errorf("got error while expanding %s.%s with expander '%s': %w",
|
|
section.Name(),
|
|
key.Name(),
|
|
expander.name,
|
|
err)
|
|
}
|
|
|
|
key.SetValue(updated)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ExpandVar(s string) (string, error) {
|
|
for _, expander := range expanders {
|
|
var err error
|
|
s, err = applyExpander(s, expander)
|
|
if err != nil {
|
|
return "", fmt.Errorf("got error while expanding expander %s: %w", expander.name, err)
|
|
}
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
func applyExpander(s string, e registeredExpander) (string, error) {
|
|
matches := regex.FindAllStringSubmatch(s, -1)
|
|
|
|
for _, match := range matches {
|
|
if len(match) < 3 {
|
|
return "", fmt.Errorf("regex error, got %d results back for match, expected 3", len(match))
|
|
}
|
|
|
|
_, isEnv := e.expander.(envExpander)
|
|
if match[1] == "__"+e.name || (match[1] == "" && isEnv) {
|
|
updated, err := e.expander.Expand(match[2])
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
s = strings.Replace(s, match[0], updated, 1)
|
|
}
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
type envExpander struct {
|
|
}
|
|
|
|
func (e envExpander) SetupExpander(file *ini.File) error {
|
|
return nil
|
|
}
|
|
|
|
func (e envExpander) Expand(s string) (string, error) {
|
|
envValue := os.Getenv(s)
|
|
|
|
// if env variable is hostname and it is empty use os.Hostname as default
|
|
if s == "HOSTNAME" && envValue == "" {
|
|
return os.Hostname()
|
|
}
|
|
|
|
return os.Getenv(s), nil
|
|
}
|
|
|
|
type fileExpander struct {
|
|
}
|
|
|
|
func (e fileExpander) SetupExpander(file *ini.File) error {
|
|
return nil
|
|
}
|
|
|
|
func (e fileExpander) Expand(s string) (string, error) {
|
|
_, err := os.Stat(s)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// nolint:gosec
|
|
// We can ignore the gosec G304 warning on this one because `s` comes from configuration section keys
|
|
f, err := ioutil.ReadFile(s)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return strings.TrimSpace(string(f)), nil
|
|
}
|