更新特定的yaml属性

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

Update specific yaml property

问题

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

我想要的是仅更新 NatIPNamestest1test2,但不改变 minPortsPerVM 的值(10000)。我该如何做到这一点?

这是 YAML 文件的内容:

  1. apiVersion: core.gardener.cloud/v1beta1
  2. kind: Shoot
  3. metadata:
  4. name: test
  5. namespace: ns
  6. spec:
  7. provider:
  8. type: aaa
  9. infrastructureConfig:
  10. apiVersion: gcp.provider.extensions.gardener.cloud/v1alpha1
  11. kind: InfrastructureConfig
  12. networks:
  13. cloudNAT:
  14. minPortsPerVM: 10000
  15. natIPNames:
  16. - name: test1

这是代码:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. gcpv1alpha1 "github.com/gardener/gardener-extension-provider-gcp/pkg/apis/gcp/v1alpha1"
  6. "github.com/gardener/gardener/pkg/apis/core/v1beta1"
  7. "io/ioutil"
  8. "k8s.io/apimachinery/pkg/runtime"
  9. "k8s.io/apimachinery/pkg/util/yaml"
  10. )
  11. func main() {
  12. shoot, e := parseShoot("test.yaml")
  13. if e != nil {
  14. fmt.Println(e)
  15. }
  16. shoot.Spec.Provider.InfrastructureConfig.Raw = encode(&gcpv1alpha1.InfrastructureConfig{
  17. Networks: gcpv1alpha1.NetworkConfig{
  18. CloudNAT: &gcpv1alpha1.CloudNAT{
  19. //MinPortsPerVM: ,
  20. NatIPNames: []gcpv1alpha1.NatIPName{
  21. {Name: "test2"},
  22. },
  23. },
  24. },
  25. })
  26. fmt.Println(shoot.Spec.Provider.InfrastructureConfig)
  27. }
  28. func parseShoot(path string) (*v1beta1.Shoot, error) {
  29. var shootSpec *v1beta1.Shoot
  30. bytes, err := ioutil.ReadFile(path)
  31. if err != nil {
  32. return nil, err
  33. }
  34. err = yaml.Unmarshal(bytes, &shootSpec)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return shootSpec, nil
  39. }
  40. func encode(obj runtime.Object) []byte {
  41. data, _ := json.Marshal(obj)
  42. return data
  43. }

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

英文:

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

  1. apiVersion: core.gardener.cloud/v1beta1
  2. kind: Shoot
  3. metadata:
  4. name: test
  5. namespace: ns
  6. spec:
  7. provider:
  8. type: aaa
  9. infrastructureConfig:
  10. apiVersion: gcp.provider.extensions.gardener.cloud/v1alpha1
  11. kind: InfrastructureConfig
  12. networks:
  13. cloudNAT:
  14. minPortsPerVM: 10000
  15. natIPNames:
  16. - name: test1

This is the code

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. gcpv1alpha1 "github.com/gardener/gardener-extension-provider-gcp/pkg/apis/gcp/v1alpha1"
  6. "github.com/gardener/gardener/pkg/apis/core/v1beta1"
  7. "io/ioutil"
  8. "k8s.io/apimachinery/pkg/runtime"
  9. "k8s.io/apimachinery/pkg/util/yaml"
  10. )
  11. func main() {
  12. shoot, e := parseShoot("test.yaml")
  13. if e != nil {
  14. fmt.Println(e)
  15. }
  16. shoot.Spec.Provider.InfrastructureConfig.Raw = encode(&gcpv1alpha1.InfrastructureConfig{
  17. Networks: gcpv1alpha1.NetworkConfig{
  18. CloudNAT: &gcpv1alpha1.CloudNAT{
  19. //MinPortsPerVM: ,
  20. NatIPNames: []gcpv1alpha1.NatIPName{
  21. {Name: "test2"},
  22. },
  23. },
  24. },
  25. })
  26. fmt.Println(shoot.Spec.Provider.InfrastructureConfig)
  27. }
  28. func parseShoot(path string) (*v1beta1.Shoot, error) {
  29. var shootSpec *v1beta1.Shoot
  30. bytes, err := ioutil.ReadFile(path)
  31. if err != nil {
  32. return nil, err
  33. }
  34. err = yaml.Unmarshal(bytes, &shootSpec)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return shootSpec, nil
  39. }
  40. func encode(obj runtime.Object) []byte {
  41. data, _ := json.Marshal(obj)
  42. return data
  43. }

答案1

得分: 2

我对园丁属性不是很了解。但是你可以创建一个InfrastructureConfig的结构体,像下面这样:

  1. type InfraConfig struct {
  2. APIVersion string `json:"apiVersion"`
  3. Kind string `json:"kind"`
  4. Networks struct {
  5. CloudNAT struct {
  6. MinPortsPerVM int `json:"minPortsPerVM"`
  7. NatIPNames []struct {
  8. Name string `json:"name"`
  9. } `json:"natIPNames"`
  10. } `json:"cloudNAT"`
  11. } `json:"networks"`
  12. }

然后创建一个引用该结构体的变量,并将Raw对象解组成该结构体,像下面这样:

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

然后你可以编辑名称(你可能需要添加一些逻辑来验证切片以更新正确的索引),将其编组并将其重新分配给InfraConfig,像下面这样:

  1. existingInfraConfig.Networks.CloudNAT.NatIPNames[0].Name = "test2"
  2. byteData, _ := json.Marshal(existingInfraConfig)
  3. shoot.Spec.Provider.InfrastructureConfig = &runtime.RawExtension{
  4. Raw: byteData,
  5. Object: nil,
  6. }

整体上,它会像这样:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/gardener/gardener/pkg/apis/core/v1beta1"
  6. "io/ioutil"
  7. "k8s.io/apimachinery/pkg/runtime"
  8. "k8s.io/apimachinery/pkg/util/yaml"
  9. )
  10. type InfraConfig struct {
  11. APIVersion string `json:"apiVersion"`
  12. Kind string `json:"kind"`
  13. Networks struct {
  14. CloudNAT struct {
  15. MinPortsPerVM int `json:"minPortsPerVM"`
  16. NatIPNames []struct {
  17. Name string `json:"name"`
  18. } `json:"natIPNames"`
  19. } `json:"cloudNAT"`
  20. } `json:"networks"`
  21. }
  22. func main() {
  23. shoot, e := parseShoot("test.yaml")
  24. if e != nil {
  25. fmt.Println(e)
  26. }
  27. var existingInfraConfig InfraConfig
  28. err := json.Unmarshal(shoot.Spec.Provider.InfrastructureConfig.Raw, &existingInfraConfig)
  29. fmt.Println(err)
  30. existingInfraConfig.Networks.CloudNAT.NatIPNames[0].Name = "test2"
  31. byteData, _ := json.Marshal(existingInfraConfig)
  32. shoot.Spec.Provider.InfrastructureConfig = &runtime.RawExtension{
  33. Raw: byteData,
  34. Object: nil,
  35. }
  36. fmt.Println(string(shoot.Spec.Provider.InfrastructureConfig.Raw))
  37. }
  38. func parseShoot(path string) (*v1beta1.Shoot, error) {
  39. var shootSpec *v1beta1.Shoot
  40. bytes, err := ioutil.ReadFile(path)
  41. if err != nil {
  42. return nil, err
  43. }
  44. err = yaml.Unmarshal(bytes, &shootSpec)
  45. if err != nil {
  46. return nil, err
  47. }
  48. return shootSpec, nil
  49. }

希望对你有所帮助!

英文:

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

  1. type InfraConfig struct {
  2. APIVersion string `json:"apiVersion"`
  3. Kind string `json:"kind"`
  4. Networks struct {
  5. CloudNAT struct {
  6. MinPortsPerVM int `json:"minPortsPerVM"`
  7. NatIPNames []struct {
  8. Name string `json:"name"`
  9. } `json:"natIPNames"`
  10. } `json:"cloudNAT"`
  11. } `json:"networks"`
  12. }

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

  1. var existingInfraConfig InfraConfig
  2. 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.

  1. existingInfraConfig.Networks.CloudNAT.NatIPNames[0].Name = "test2"
  2. byteData, _ := json.Marshal(existingInfraConfig)
  3. shoot.Spec.Provider.InfrastructureConfig = &runtime.RawExtension{
  4. Raw: byteData,
  5. Object: nil,
  6. }

On the whole, it would be like

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/gardener/gardener/pkg/apis/core/v1beta1"
  6. "io/ioutil"
  7. "k8s.io/apimachinery/pkg/runtime"
  8. "k8s.io/apimachinery/pkg/util/yaml"
  9. )
  10. type InfraConfig struct {
  11. APIVersion string `json:"apiVersion"`
  12. Kind string `json:"kind"`
  13. Networks struct {
  14. CloudNAT struct {
  15. MinPortsPerVM int `json:"minPortsPerVM"`
  16. NatIPNames []struct {
  17. Name string `json:"name"`
  18. } `json:"natIPNames"`
  19. } `json:"cloudNAT"`
  20. } `json:"networks"`
  21. }
  22. func main() {
  23. shoot, e := parseShoot("test.yaml")
  24. if e != nil {
  25. fmt.Println(e)
  26. }
  27. var existingInfraConfig InfraConfig
  28. err := json.Unmarshal(shoot.Spec.Provider.InfrastructureConfig.Raw, &existingInfraConfig)
  29. fmt.Println(err)
  30. existingInfraConfig.Networks.CloudNAT.NatIPNames[0].Name = "test2"
  31. byteData, _ := json.Marshal(existingInfraConfig)
  32. shoot.Spec.Provider.InfrastructureConfig = &runtime.RawExtension{
  33. Raw: byteData,
  34. Object: nil,
  35. }
  36. fmt.Println(string(shoot.Spec.Provider.InfrastructureConfig.Raw))
  37. }
  38. func parseShoot(path string) (*v1beta1.Shoot, error) {
  39. var shootSpec *v1beta1.Shoot
  40. bytes, err := ioutil.ReadFile(path)
  41. if err != nil {
  42. return nil, err
  43. }
  44. err = yaml.Unmarshal(bytes, &shootSpec)
  45. if err != nil {
  46. return nil, err
  47. }
  48. return shootSpec, nil
  49. }

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:

确定