英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论