如何使用YAML编组嵌套的Golang结构体?

huangapple go评论82阅读模式
英文:

How can I marshall a golang nested structs with YAML

问题

我如何表示这个结构的匹配标签部分以便打印出来。我尝试以类似于元数据的格式添加'NetworkPolicySpecPodSelector'结构,但我的格式是不正确的。

package main

import (
	"fmt"
	"io/ioutil"

	"gopkg.in/yaml.v2"
)

type Metadata struct {
	Name      string `yaml:"name"`
	Namespace string `yaml:"namespace"`
}

type Spec struct {
	PodSelector NetworkPolicySpecPodSelector `yaml:"Spec"`
}

type NetworkPolicySpecPodSelector struct {
	MatchLabels map[string][]string `yaml:"matchLabels"`
}

type Ingress struct {
}

type NetworkPolicy struct {
	ApiVersion string   `yaml:"apiVersion"`
	Kind       string   `yaml:"kind"`
	Metadata   Metadata `yaml:"metadata"`
	Spec       struct {
		PodSelector NetworkPolicySpecPodSelector
	}
	PolicyTypes []string `yaml:"policyTypes"`
}

func main() {
	np := NetworkPolicy{
		ApiVersion: "networking.k8s.io/v1",
		Kind:       "NetworkPolicy",
		Metadata: Metadata{
			Name:      "allow-ingress",
			Namespace: "default",
		},
		PolicyTypes: []string{"Ingress"},
	}

	np.Spec.PodSelector.MatchLabels = make(map[string][]string)
	np.Spec.PodSelector.MatchLabels["env"] = []string{"prod"}

	yamlData, err := yaml.Marshal(&np)

	if err != nil {
		fmt.Printf("Error while Marshaling. %v", err)
	}

	fileName := "test.yaml"
	err = ioutil.WriteFile(fileName, yamlData, 0644)
	if err != nil {
		panic("Unable to write data into the file")
	}
}

期望的输出是:

apiversion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress
  namespace: default
spec:
  podselector:
    matchLabels:
      env: prod
policyTypes:
- Ingress

目前还需要进一步完善,但我在这部分遇到了困难。项目的目标是使用YAML输出Kubernetes网络策略。

英文:

How do I represent the match labels section of this struct to print out.
I try to add the 'NetworkPolicySpecPodSelector' struct in a format like metadata but my format is incorrect.

package main
import (
"fmt"
"io/ioutil"
"gopkg.in/yaml.v2"
)
type Metadata struct {
Name      string `yaml:"name"`
Namespace string `yaml:"namespace"`
}
type Spec struct {
PodSelector NetworkPolicySpecPodSelector `yaml:"Spec"`
}
type NetworkPolicySpecPodSelector struct {
MatchLabels map[string][]string `yaml:"matchLabels"`
}
type Ingress struct {
}
type NetworkPolicy struct {
ApiVersion string   `yaml:"apiVersion`
Kind       string   `yaml:"kind"`
Metadata   Metadata `yaml:"metadata"`
Spec       struct {
PodSelector NetworkPolicySpecPodSelector
}
PolicyTypes []string `yaml:"policyTypes"`
}
func main() {
np := NetworkPolicy{
ApiVersion: "networking.k8s.io/v1",
Kind:       "NetworkPolicy",
Metadata: Metadata{
Name:      "allow-ingress",
Namespace: "default",
},
PolicyTypes: []string{"Ingress"},
}
yamlData, err := yaml.Marshal(&np)
if err != nil {
fmt.Printf("Error while Marshaling. %v", err)
}
fileName := "test.yaml"
err = ioutil.WriteFile(fileName, yamlData, 0644)
if err != nil {
panic("Unable to write data into the file")
}
}

My output is here:

apiversion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: default
spec:
podselector:
matchLabels: {}
policyTypes:
- Ingress

Desired output:

apiversion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: default
spec:
podselector:
matchLabels: 
env:prod
policyTypes:
- Ingress

still needs to grow but Im struggling with this part. Goal of the project is to output a Kubernetes network policy using YAML.

答案1

得分: 0

首先,你需要修复结构字段标签,以反映你期望的结构。NetworkPolicy 中的 Spec 需要序列化为键 spec,它的字段 PodSelector 应该是 podselector

type NetworkPolicy struct {
	ApiVersion  string   `yaml:"apiVersion"`
	Kind        string   `yaml:"kind"`
	Metadata    Metadata `yaml:"metadata"`
	Spec        Spec     `yaml:"spec"`
	PolicyTypes []string `yaml:"policyTypes"`
}

type Spec struct {
	PodSelector NetworkPolicySpecPodSelector `yaml:"podselector"`
}

然后,你可以简单地使用字面量:

np := NetworkPolicy{
	ApiVersion: "networking.k8s.io/v1",
	Kind:       "NetworkPolicy",
	Metadata: Metadata{
		Name:      "allow-ingress",
		Namespace: "default",
	},
	Spec: Spec{
		PodSelector: NetworkPolicySpecPodSelector{
			MatchLabels: map[string][]string{
				"env": []string{"prod"},
			},
		},
	},
	PolicyTypes: []string{"Ingress"},
}

这是在 playground 上的完整示例:https://go.dev/play/p/xJ-mmCVcv2M

注意:在你的代码片段中,MatchLabels 的类型是 map[string][]string。尽管从示例中看起来你想要的是 map[string]string,但我保持了原样。

英文:

First you need to fix struct field tags to reflect your desired structure. Spec in NetworkPolicy needs to serialize as key spec and its field PodSelector as podselector:

type NetworkPolicy struct {
	ApiVersion  string   `yaml:"apiVersion`
	Kind        string   `yaml:"kind"`
	Metadata    Metadata `yaml:"metadata"`
	Spec        Spec     `yaml:"spec"`
	PolicyTypes []string `yaml:"policyTypes"`
}

type Spec struct {
	PodSelector NetworkPolicySpecPodSelector `yaml:"podselector"`
}

Then you can simply use literals:

	np := NetworkPolicy{
		ApiVersion: "networking.k8s.io/v1",
		Kind:       "NetworkPolicy",
		Metadata: Metadata{
			Name:      "allow-ingress",
			Namespace: "default",
		},
		Spec: Spec{
			PodSelector: NetworkPolicySpecPodSelector{
				MatchLabels: map[string][]string{
					"env": []string{"prod"},
				},
			},
		},
		PolicyTypes: []string{"Ingress"},
	}

Here is full example on playground: https://go.dev/play/p/xJ-mmCVcv2M

NOTE: In your code snippet the type of MatchLabels is map[string][]string. I kept it like that although from example it looks like you want map[string]string.

huangapple
  • 本文由 发表于 2022年6月23日 07:54:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/72723119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定