更新特定的yaml属性

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

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
}

请注意,这是你要翻译的内容,我已经将其翻译成中文。

英文:

Im trying to parse a yaml file and update only one property,
the problem is that the type is RAW and when I update one field it update the whole object,

what I want is to update only NatIPNames from test1 to test2,
but without changing the value of minPortsPerVM(10000) How can I do it?

This is the 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

This is the code

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
}

答案1

得分: 2

我对园丁属性不是很了解。但是你可以创建一个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
}

希望对你有所帮助!

英文:

I am not well aware of the gardener properties. But what you can do is create a struct for the InfrastructureConfig like below

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"`
}

and create a variable referencing that struct and unmarshal the Raw object into that like below.

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

then you can edit on the name (you might want to add some logic to validate the slice to update the right index) and marshal it and assign it back to the InfraConfig like below.

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

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

On the whole, it would be like

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
}


huangapple
  • 本文由 发表于 2022年3月30日 02:36:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/71667203.html
匿名

发表评论

匿名网友

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

确定