J'essaye d'analyser un fichier yaml avec Go. Malheureusement, je n'arrive pas à comprendre comment. Le fichier yaml que j'ai est le suivant:
---
firewall_network_rules:
rule1:
src: blablabla-Host
dst: blabla-hostname
...
J'ai ce code Go, mais ça ne marche pas:
package main
import (
"fmt"
"io/ioutil"
"path/filepath"
"gopkg.in/yaml.v2"
)
type Config struct {
Firewall_network_rules map[string][]string
}
func main() {
filename, _ := filepath.Abs("./fruits.yml")
yamlFile, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
var config Config
err = yaml.Unmarshal(yamlFile, &config)
if err != nil {
panic(err)
}
fmt.Printf("Value: %#v\n", config.Firewall_network_rules)
}
Lorsque je lance ceci, je reçois une erreur. Je pense que c’est parce que je n’ai pas créé de structure pour les clés/valeurs src et dst. Pour votre information: quand je change cela en liste, ça marche.
Donc, le code ci-dessus analyse ceci:
---
firewall_network_rules:
rule1:
- value1
- value2
...
Si vous travaillez avec Google Cloud ou Kubernetes plus spécifiquement et souhaitez analyser un service.yaml comme ceci:
apiVersion: v1
kind: Service
metadata:
name: myName
namespace: default
labels:
router.deis.io/routable: "true"
annotations:
router.deis.io/domains: ""
spec:
type: NodePort
selector:
app: myName
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
Fournir un exemple concret afin que vous compreniez comment écrire une imbrication.
type Service struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata struct {
Name string `yaml:"name"`
Namespace string `yaml:"namespace"`
Labels struct {
RouterDeisIoRoutable string `yaml:"router.deis.io/routable"`
} `yaml:"labels"`
Annotations struct {
RouterDeisIoDomains string `yaml:"router.deis.io/domains"`
} `yaml:"annotations"`
} `yaml:"metadata"`
Spec struct {
Type string `yaml:"type"`
Selector struct {
App string `yaml:"app"`
} `yaml:"selector"`
Ports []struct {
Name string `yaml:"name"`
Port int `yaml:"port"`
TargetPort int `yaml:"targetPort"`
NodePort int `yaml:"nodePort,omitempty"`
} `yaml:"ports"`
} `yaml:"spec"`
}
Il existe un service pratique appelé json-to-go https://mholt.github.io/json-to-go/ qui convertit json en structs go, convertissez simplement votre YAML en JSON et entrez ce service obtenir une structure auto-générée.
Et le dernier retour, comme l'a écrit une affiche précédente:
var service Service
err = yaml.Unmarshal(yourFile, &service)
if err != nil {
panic(err)
}
fmt.Print(service.Metadata.Name)
Pourquoi ne pas organiser votre fichier yaml comme ci-dessous si vous ne vous souciez pas du nom de la règle?
---
firewall_network_rules:
-
name: rule1
src: blablabla-Host
dst: blabla-hostname
-
name: rule2
src: bla-Host
dst: bla-hostname
Donc, le code sera comme ça, il est propre et extensible:
type Rule struct {
Name string `yaml:"name"`
Src string `yaml:"src"`
Dst string `yaml:"dst"`
}
type Config struct {
FirewallNetworkRules []Rule `yaml:"firewall_network_rules"`
}
Eh bien, je pense l’avoir compris moi-même. Le code suivant fonctionne bien. Des suggestions/améliorations?
package main
import (
"fmt"
"io/ioutil"
"path/filepath"
"gopkg.in/yaml.v2"
)
type Config struct {
Firewall_network_rules map[string]Options
}
type Options struct {
Src string
Dst string
}
func main() {
filename, _ := filepath.Abs("./fruits.yml")
yamlFile, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
var config Config
err = yaml.Unmarshal(yamlFile, &config)
if err != nil {
panic(err)
}
fmt.Printf("Value: %#v\n", config.Firewall_network_rules)
}
Si votre fichier YAML est simple (imbrication simple), comme suit
mongo:
DB: database
COL: collection
log:
error: log/error/error.log
api:
key: jhgwewbcjwefwjfg
Ici, vous pouvez utiliser l'interface au lieu de déclarer struct.
main(){
config := Config()
mongoConfig := config["mongo"]
mongo.MongoDial(
String(
Get(mongoConfig, "DB")
),
String(
Get(mongoConfig, "COL")
)
)
}
func Config() map[string]interface{} {
filename, _ := filepath.Abs("configs/config.yaml")
yamlFile, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
var config map[string]interface{}
err = yaml.Unmarshal(yamlFile, &config)
if err != nil {
panic(err)
}
return config
}
func Get(this interface{}, key string) interface{} {
return this.(map[interface{}]interface{})[key]
}
func String(payload interface{}) string {
var load string
if pay, oh := payload.(string); oh {
load = pay
}else{
load = ""
}
return load
}
Cela fonctionne très bien pour une imbrication de niveau 1; si vous avez une imbrication complexe, il est recommandé d'utiliser struct
.