Home > Back-end >  How can I marshall a golang nested structs with YAML
How can I marshall a golang nested structs with YAML

Time:06-23

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.

CodePudding user response:

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.

  •  Tags:  
  • go
  • Related