更新特定的 yaml 属性

Update specific yaml property

我正在尝试解析一个 yaml 文件并只更新一个 属性, 问题是类型是 RAW,当我更新一个字段时,它会更新整个对象,

我想要的是 仅更新​​ NatIPNamestest1test2, 但是 不改变 minPortsPerVM(10000) 的值我该怎么做?

这是 yaml

apiVersion: core.gardener.cloud/v1beta1
kind: Shoot
metadata:
  name: test
  namespace: ns
spec:
  provider:
    type: aaa
    infrastructureConfig:
      apiVersion: gcp.provider.extensions.gardener.cloud/v1alpha1
      kind: InfrastructureConfig
      networks:
        cloudNAT:
          minPortsPerVM: 10000
          natIPNames:
            - name: test1

这是代码

package main

import (
    "encoding/json"
    "fmt"
    gcpv1alpha1 "github.com/gardener/gardener-extension-provider-gcp/pkg/apis/gcp/v1alpha1"
    "github.com/gardener/gardener/pkg/apis/core/v1beta1"
    "io/ioutil"
    "k8s.io/apimachinery/pkg/runtime"
    "k8s.io/apimachinery/pkg/util/yaml"
)

func main() {
    shoot, e := parseShoot("test.yaml")
    if e != nil {
        fmt.Println(e)
    }

    shoot.Spec.Provider.InfrastructureConfig.Raw = encode(&gcpv1alpha1.InfrastructureConfig{
        Networks: gcpv1alpha1.NetworkConfig{
            CloudNAT: &gcpv1alpha1.CloudNAT{
                //MinPortsPerVM: ,
                NatIPNames: []gcpv1alpha1.NatIPName{
                    {Name: "test2"},
                },
            },
        },
    })
    fmt.Println(shoot.Spec.Provider.InfrastructureConfig)
}

func parseShoot(path string) (*v1beta1.Shoot, error) {
    var shootSpec *v1beta1.Shoot
    bytes, err := ioutil.ReadFile(path)
    if err != nil {
        return nil, err
    }
    err = yaml.Unmarshal(bytes, &shootSpec)
    if err != nil {
        return nil, err
    }
    return shootSpec, nil
}

func encode(obj runtime.Object) []byte {
    data, _ := json.Marshal(obj)
    return data
}

我不是很了解园丁属性。但是你可以做的是为 InfrastructureConfig 创建一个结构,如下所示

type InfraConfig struct {
    APIVersion string `json:"apiVersion"`
    Kind       string `json:"kind"`
    Networks   struct {
        CloudNAT struct {
            MinPortsPerVM int `json:"minPortsPerVM"`
            NatIPNames    []struct {
                Name string `json:"name"`
            } `json:"natIPNames"`
        } `json:"cloudNAT"`
    } `json:"networks"`
}

并创建一个引用该结构的变量并将 Raw 对象解组为如下所示。

    var existingInfraConfig InfraConfig
    err := json.Unmarshal(shoot.Spec.Provider.InfrastructureConfig.Raw, &existingInfraConfig)

然后您可以编辑名称(您可能想添加一些逻辑来验证切片以更新正确的索引)并将其编组并将其分配回 InfraConfig,如下所示。

    existingInfraConfig.Networks.CloudNAT.NatIPNames[0].Name = "test2"
    byteData, _ := json.Marshal(existingInfraConfig)

    shoot.Spec.Provider.InfrastructureConfig = &runtime.RawExtension{
        Raw:    byteData,
        Object: nil,
    }

总的来说,就是这样

package main

import (
    "encoding/json"
    "fmt"
    "github.com/gardener/gardener/pkg/apis/core/v1beta1"
    "io/ioutil"
    "k8s.io/apimachinery/pkg/runtime"
    "k8s.io/apimachinery/pkg/util/yaml"
)

type InfraConfig struct {
    APIVersion string `json:"apiVersion"`
    Kind       string `json:"kind"`
    Networks   struct {
        CloudNAT struct {
            MinPortsPerVM int `json:"minPortsPerVM"`
            NatIPNames    []struct {
                Name string `json:"name"`
            } `json:"natIPNames"`
        } `json:"cloudNAT"`
    } `json:"networks"`
}

func main() {
    shoot, e := parseShoot("test.yaml")
    if e != nil {
        fmt.Println(e)
    }

    var existingInfraConfig InfraConfig
    err := json.Unmarshal(shoot.Spec.Provider.InfrastructureConfig.Raw, &existingInfraConfig)
    fmt.Println(err)

    existingInfraConfig.Networks.CloudNAT.NatIPNames[0].Name = "test2"
    byteData, _ := json.Marshal(existingInfraConfig)

    shoot.Spec.Provider.InfrastructureConfig = &runtime.RawExtension{
        Raw:    byteData,
        Object: nil,
    }
    fmt.Println(string(shoot.Spec.Provider.InfrastructureConfig.Raw))

}

func parseShoot(path string) (*v1beta1.Shoot, error) {
    var shootSpec *v1beta1.Shoot
    bytes, err := ioutil.ReadFile(path)
    if err != nil {
        return nil, err
    }
    err = yaml.Unmarshal(bytes, &shootSpec)
    if err != nil {
        return nil, err
    }
    return shootSpec, nil
}