I need to add entry to a yaml file from struct value config.Sif["snk_prod"]
(I need to fill it on runtime) and try the following , I tried the following but I got an error when filling the struct, any idea?
package main
import "gopkg.in/yaml.v3"
const document = `
spec:
mec:
customConfig:
sif:
prom_exporter:
type: prometheus_exporter
snk_dev:
type: sk_hc_logs
inputs:
- tesslt
ep: ${NT}
dken: ${SN}
`
type YamlObject map[string]any
type CustomConfig struct {
Sif map[string]interface{} `yaml:"sif,omitempty"`
}
type ecfg struct {
Type string `yaml:"type,omitempty"`
Inputs []string `yaml:"inputs,omitempty"`
Ep string `yaml:"ep,omitempty"`
Dken string `yaml:"dken,omitempty"`
}
func main() {
t := CustomConfig{}
config := &t
// -------I need to add it as struct values as I got the values on runtime dynamically
config.Sif["snk_prod"] = ecfg{
Type: "sk_hc_ls",
Inputs: []string{"tesslt"},
Ep: "${NT}",
}
yamlBytes, err := yaml.Marshal(t)
doc := make(YamlObject)
if err := yaml.Unmarshal([]byte(document), &doc); err != nil {
panic(err)
}
addon := make(YamlObject)
if err := yaml.Unmarshal(yamlBytes, &addon); err != nil {
panic(err)
}
node := findChild(doc, "spec", "mec", "customConfig", "sif")
if node == nil {
panic("Must not happen")
}
for key, val := range addon {
(*node)[key] = val
}
outDoc, err := yaml.Marshal(doc)
if err != nil {
panic(err)
}
println(string(outDoc))
}
func findChild(obj YamlObject, path ...string) *YamlObject {
if len(path) == 0 {
return &obj
}
key := path[0]
child, ok := obj[key]
if !ok {
return nil
}
obj, ok = child.(YamlObject)
if !ok {
return nil
}
return findChild(obj, path[1:]...)
}
https://go.dev/play/p/6CHsOJPXqpw
After searching I found this answer https://stackoverflow.com/a/74089724/6340176 which is quite similar to mine, the change is the that I need to add it as struct value
at the end I need to add new entry under sif
At the end The output should be like following
spec:
mec:
customConfig:
sif:
prom_exporter:
type: prometheus_exporter
snk_dev:
type: sk_hc_logs
inputs:
- tesslt
ep: ${NT}
dken: ${SN}
snk_prod:
type: sk_hc_ls
inputs:
- tesslt
ep: ${NT}
CodePudding user response:
Replace the creation of the yamlBytes
as follows:
t := make(map[string]interface{})
t["snk_prod"] = ecfg{
Type: "sk_hc_ls",
Inputs: []string{"tesslt"},
Ep: "${NT}",
}
yamlBytes, err := yaml.Marshal(t)
Then you will get the expected result.
BTW: The panic is triggered because you are trying to insert a value into an uninitialized map (config.Sif
is nil
). You could simply create an empty map using, for example, the following line of code before assigning values:
config.Sif = make(map[string]interface{})
but there would be an additional unwanted sif
node in the code, e.g. something like this:
...
sif:
prom_exporter:
type: prometheus_exporter
sif:
snk_prod:
...
Therefore, the yaml snippet to be added dynamically should be generated as shown at the beginning.