I am reading in a yaml file, and unmarshaling it into a map[interface{}]interface{}
. The goal is to replace a certain value within the yaml, and update the file read in with just that value replaced. I'm not sure how to parse the map though to get to the specific key (password
) I want to change. I believe you can use reflect
, but I'm not 100% sure of the syntax
YAML file I am reading in (config.yml
):
i_name: example
instances:
- name: test-instance
command: get
arguments:
hostname: localhost
port: 203
username: test
password: testing123
labels:
env: dev
Code thus far:
func replaceConfigPassword() {
yamlFile, err := ioutil.ReadFile("config.yml")
fatalIfErr(err)
m := make(map[interface{}]interface{})
err = yaml.Unmarshal(yamlFile, &m)
fatalIfErr(err)
fmt.Println(m)
val := reflect.ValueOf(m["instances"]["arguments"]["password"])
fmt.Println("val=", val)
The following shows how you might step through the yaml to arrive at the password:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
func main() {
in := []byte(`
i_name: example
instances:
- name: test-instance
command: get
arguments:
hostname: localhost
port: 203
username: test
password: testing123
labels:
env: dev
`)
m := make(map[string]interface{})
if err := yaml.Unmarshal(in, &m); err != nil {
panic(err)
}
fmt.Printf("%+v
", m)
instances := m["instances"].([]interface{})
fmt.Printf("%+v
", instances)
first := instances[0]
fmt.Printf("%+v
", first)
arguments := first.(map[interface{}]interface{})["arguments"]
fmt.Printf("%+v
", arguments)
password := arguments.(map[interface{}]interface{})["password"]
fmt.Printf("%+v
", password)
}
$ go run main.go
map[i_name:example instances:[map[name:test-instance command:get arguments:map[password:testing123 hostname:localhost port:203 username:test] labels:map[env:dev]]]]
[map[name:test-instance command:get arguments:map[hostname:localhost port:203 username:test password:testing123] labels:map[env:dev]]]
map[name:test-instance command:get arguments:map[hostname:localhost port:203 username:test password:testing123] labels:map[env:dev]]
map[username:test password:testing123 hostname:localhost port:203]
testing123
If you know the input structure before hand, another option could be to model it explicitly:
type Config struct {
IName string `yaml:"i_name"`
Instances []struct{
Name string
Command string
Arguments map[string]interface{}
Labels map[string]string
}
}
var c Config
if err := yaml.Unmarshal(in, &c); err != nil {
panic(err)
}
fmt.Printf("%+v
", c)
fmt.Printf("%+v
", c.Instances[0].Arguments["password"])
$ go run main.go
{IName:example Instances:[{Name:test-instance Command:get Arguments:map[hostname:localhost port:203 username:test password:testing123] Labels:map[env:dev]}]}
testing123