Go语言 在YAML文件中使用环境变量

rvpgvaaj  于 11个月前  发布在  Go
关注(0)|答案(3)|浏览(174)

我有一个GO脚本,可以生成寻呼机的呼叫报告,它有自己的config.yaml文件:

# PagerDuty auth token
pdAuthToken: 12345

# Explicitly set report time range (RFC822)
reportTimeRange:
  start: 01 Jan 20 00:00 UTC
  end: 01 Feb 20 00:00 UTC

# Rotation general information
rotationInfo:
  dailyRotationStartsAt: 8
  checkRotationChangeEvery: 30 # minutes

字符串
我需要在config.yaml文件中传递环境变量。我试着这样使用${THE_VARIABLE}

reportTimeRange:
    start: ${THE_VARIABLE}


有没有人可以帮助我如何在config.yaml文件中传递我的Linux环境变量,而不需要编辑脚本。

cu6pst1q

cu6pst1q1#

解组yaml文件后,您可以对结果使用reflect来更新其值与您选择的变量格式匹配的任何string字段。

var reVar = regexp.MustCompile(`^\${(\w+)}$`)

func fromenv(v interface{}) {
    _fromenv(reflect.ValueOf(v).Elem())// assumes pointer to struct
}

// recursive
func _fromenv(rv reflect.Value) {
    for i := 0; i < rv.NumField(); i++ {
        fv := rv.Field(i)
        if fv.Kind() == reflect.Ptr {
            fv = fv.Elem()
        }
        if fv.Kind() == reflect.Struct {
            _fromenv(fv)
            continue
        }
        if fv.Kind() == reflect.String {
            match := reVar.FindStringSubmatch(fv.String())
            if len(match) > 1 {
                fv.SetString(os.Getenv(match[1]))
            }
        }
    }
}

字符串
https://play.golang.org/p/1zuK7Mhtvsa
或者,您可以声明实现yaml.Unmarshaler接口的类型,并将这些类型用于配置结构中的字段,这些字段期望相应的yaml属性包含环境变量。

type Config struct {
    ReportTimeRange struct {
        Start StringFromEnv `yaml:"start"`
    } `yaml:"reportTimeRange"`
}

var reVar = regexp.MustCompile(`^\${(\w+)}$`)

type StringFromEnv string

func (e *StringFromEnv) UnmarshalYAML(value *yaml.Node) error {
    var s string
    if err := value.Decode(&s); err != nil {
        return err
    }
    if match := reVar.FindStringSubmatch(s); len(match) > 0 {
        *e = StringFromEnv(os.Getenv(match[1]))
    } else {
        *e = StringFromEnv(s)
    }
    return nil
}


https://play.golang.org/p/Zy0rXJ7RRdC

syqv5f0l

syqv5f0l2#

我的理解是,您希望在程序启动时将占位符{{ .THE_VARIABLE }}替换为内存中的环境变量,而不修改yaml文件。
我们的想法是将yaml文件加载到一个var中,使用template.Execute替换数据。最后解组字符串。
我只想简单一点。
YAML文件:
Start: {{ .THE_VARIABLE }}
替换数据:

fileData, _ := ioutil.ReadFile("test.yml")
var finalData bytes.Buffer
t := template.New("config")
t, err := t.Parse(string(fileData))
if err != nil {
    panic(err)
}

data := struct {
    THE_VARIABLE int
}{
    THE_VARIABLE: 30,  // replace with os.Getenv("FOO")
}
t.Execute(&finalData, data)
str := finalData.String()
fmt.Println(str)
// unmarshal YAML here - from finalData.Bytes()

字符串
输出量:
Start: 30

gdrx4gfi

gdrx4gfi3#

最简单的方法是使用os.ExpandEnv。在https://go.dev/src/os/env.go中检查os.Expand以了解它是如何工作的,而os.ExpandEnv只是Expand(s, Getenv)的 Package 器。
这是如何使用它:读取文件,替换占位符并解析为yaml

type Config struct {
    //some properties
}

func parseConfig(path string) (*Config, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, err
    }
    replaced := os.ExpandEnv(string(data))
    cfg := &Config{}
    err = yaml.Unmarshal([]byte(replaced), cfg)
    return cfg, err
}

字符串

相关问题