mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
	
	
		
			148 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
		
		
			
		
	
	
			148 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
|  | package setting | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"fmt" | ||
|  | 	"io/ioutil" | ||
|  | 	"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 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	f, err := ioutil.ReadFile(s) | ||
|  | 	if err != nil { | ||
|  | 		return "", err | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return strings.TrimSpace(string(f)), nil | ||
|  | } |