I'm unmarshalling a yaml file snmp.yml. and I was wondering if I could get suggestions on creating better structs. This is what I have for now, but I'm guessing the structs I'm creating for Metric is fine but the SNMPyaml needs better restructuring to be fully able to consume the unmarshalled data correctly.
Any suggestions/feedback here is highly appreciated. Thank you in advance!
package system
import (
"fmt"
"io/ioutil"
"log"
"path/filepath"
y "gopkg.in/yaml.v2"
)
//SNMPyaml struct
type SNMPyaml struct {
Metrics Metric `yaml:"metrics"`
}
//Metric exportable
type Metric struct {
Name string `yaml:"name,omitempty"`
Oid string `yaml:"oid"`
Type string `yaml:"type"`
Help string `yaml:"help,omitempty"`
}
// Yamlparser
func Yamlparser() {
// Read the snmp.yml file
absPath, _ := filepath.Abs("./app/snmp.yml")
yamlFile, yamlerror := ioutil.ReadFile(absPath)
if yamlerror != nil {
log.Fatalf("ioutil err: %v", yamlerror)
}
//Unmarshall
var c SNMPyaml
err := y.Unmarshal(yamlFile, &c)
if err != nil {
log.Fatal(err)
}
fmt.Print(c)
}
metrics:
- name: sysStatClientCurConns
oid: 1.3.6.1.4.1.3375.2.1.1.2.1.8
type: gauge
indexes:
- labelname: sysStatClientCurConns
type: gauge
- name: sysClientsslStatCurConns
oid: 1.3.6.1.4.1.3375.2.1.1.2.9.2
type: gauge
indexes:
- labelname: sysClientsslStatCurConns
type: gauge
- name: sysClientSslStatTotNativeConns
oid: 1.3.6.1.4.1.3375.2.1.1.2.9.6
type: gauge
indexes:
- labelname: sysClientSslStatTotNativeConns
type: gauge
The error I'm getting for this is:
2019/07/31 23:25:58 yaml: line 25: mapping values are not allowed in this context
exit status 1
In your input metrics
is a sequence (list), so you cannot marshal that into a single Metric
. Use a slice: []Metric
:
type SNMPyaml struct {
Metrics []Metric `yaml:"metrics"`
}
Also there is an indexes
field, another sequence which you don't have a corresponding field in your Metric
struct, and you have an unnecessary Help
(at least in the input you provided there is no such field):
type Metric struct {
Name string `yaml:"name,omitempty"`
Oid string `yaml:"oid"`
Type string `yaml:"type"`
Indexes []Index `yaml:"indexes"`
}
Where indexes can be modeled with this struct:
type Index struct {
LabelName string `yaml:"labelname"`
Type string `yaml:"type"`
}
With these changes it runs, try it on the Go Playground, and produces the following output:
{[{sysStatClientCurConns 1.3.6.1.4.1.3375.2.1.1.2.1.8 gauge [{sysStatClientCurConns gauge}]} {sysClientsslStatCurConns 1.3.6.1.4.1.3375.2.1.1.2.9.2 gauge [{sysClientsslStatCurConns gauge}]} {sysClientSslStatTotNativeConns 1.3.6.1.4.1.3375.2.1.1.2.9.6 gauge [{sysClientSslStatTotNativeConns gauge}]}]}
Also note that there is an online YAML-to-Go converter, where you input your YAML source, and it produces Go data structures modeling your input: https://mengzhuo.github.io/yaml-to-go/
The generated code uses unnamed structs (which is a pain if you have to create values of), but it's a good starting point, and you can easily refactor them to named types. It produces the following model from your YAML input:
type AutoGenerated struct {
Metrics []struct {
Name string `yaml:"name"`
Oid string `yaml:"oid"`
Type string `yaml:"type"`
Indexes []struct {
Labelname string `yaml:"labelname"`
Type string `yaml:"type"`
} `yaml:"indexes"`
} `yaml:"metrics"`
}