修改现有的Yaml文件并添加新数据和注释

Ray*_*n D 8 json yaml abstract-syntax-tree go

我最近看到go yaml lib具有新版本(V3)

具有节点功能(在我看来,这是一个杀手级功能:)),它可以在不更改文件结构的情况下帮助大量修改yaml

但是由于它是相当新的(从上周开始),所以我没有找到一些有用的文档和所需的上下文示例(添加新的对象/节点并不删除注释的情况下保持文件结构不变)等。

我需要的是操作yaml文件

例如

可以说我有这个yaml文件

version: 1
type: verbose
kind : bfr

# my list of applications
applications:
  - name: app1
    kind: nodejs
    path: app1
    exec:
      platforms: k8s
      builder: test
Run Code Online (Sandbox Code Playgroud)

现在,我有一个json对象(例如带有app2),需要将其插入到现有文件中

[

    {
        "comment: "Second app",
        "name": "app2",
        "kind": "golang",
        "path": "app2",
        "exec": {
            "platforms": "dockerh",
            "builder": "test"
        }
    }
]
Run Code Online (Sandbox Code Playgroud)

我需要在第一个应用程序之后将其添加到yml文件中(应用程序是应用程序的数组)

version: 1
type: verbose
kind : bfr

# my list of applications
applications:

#  First app
  - name: app1
    kind: nodejs
    path: app1
    exec:
      platforms: k8s
      builder: test

# Second app
  - name: app2
    kind: golang
    path: app2
    exec:
      platforms: dockerh
      builder: test
Run Code Online (Sandbox Code Playgroud)

是否可以从yaml文件中添加新的json对象?也删除现有的

我也找到了这个博客 https://blog.ubuntu.com/2019/04/05/api-v3-of-the-yaml-package-for-go-is-available

这是代表对象的类型

type VTS struct {
    version string       `yaml:"version"`
    types   string       `yaml:"type"`
    kind    string       `yaml:"kind,omitempty"`
    apps    Applications `yaml:"applications,omitempty"`
}

type Applications []struct {
    Name string `yaml:"name,omitempty"`
    Kind string `yaml:"kind,omitempty"`
    Path string `yaml:"path,omitempty"`
    Exec struct {
        Platforms string `yaml:"platforms,omitempty"`
        Builder   string `yaml:"builder,omitempty"`
    } `yaml:"exec,omitempty"`
}
Run Code Online (Sandbox Code Playgroud)

更新

测试了wiil7200 我提供的解决方案后,发现了2个问题

我用最后写到文件 err = ioutil.WriteFile("output.yaml", b, 0644)

和yaml输出有2个问题。

  1. 应用程序的数组从注释开始,应该从名称开始

  2. name输入后,该kind属性和之后的所有其他属性均未与name

知道如何解决那些问题吗?考虑到这个comments问题,可以说我是从其他属性而不是从json获得的(如果它使它更简单)

version: 1
type: verbose
kind: bfr


# my list of applications
applications:
-   #  First app
name: app1
    kind: nodejs
    path: app1
    exec:
        platforms: k8s
        builder: test
-   # test 1
name: app2
    kind: golang
    path: app2
    exec:
        platform: dockerh
        builder: test
Run Code Online (Sandbox Code Playgroud)

wil*_*200 7

首先,让我开始说使用yaml.Node从有效yaml编组时不会产生有效的yaml,如以下示例所示。可能应该提出问题。

package main

import (
    "fmt"
    "log"

    "gopkg.in/yaml.v3"
)

var (
    sourceYaml = `version: 1
type: verbose
kind : bfr

# my list of applications
applications:

#  First app
  - name: app1
    kind: nodejs
    path: app1
    exec:
      platforms: k8s
      builder: test
`
)

func main() {
    t := yaml.Node{}

    err := yaml.Unmarshal([]byte(sourceYaml), &t)
    if err != nil {
        log.Fatalf("error: %v", err)
    }

    b, err := yaml.Marshal(&t)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(b))
}
Run Code Online (Sandbox Code Playgroud)

在go版本go1.12.3 windows / amd64中产生以下无效的Yaml

version: 1
type: verbose
kind: bfr


# my list of applications
applications:
-   #  First app
name: app1
    kind: nodejs
    path: app1
    exec:
        platforms: k8s
        builder: test
Run Code Online (Sandbox Code Playgroud)

其次,使用诸如

version: 1
type: verbose
kind: bfr


# my list of applications
applications:
-   #  First app
name: app1
    kind: nodejs
    path: app1
    exec:
        platforms: k8s
        builder: test
Run Code Online (Sandbox Code Playgroud)

从ubuntu的博客和源文档中可以看出,它可以正确识别结构中的节点(分别是节点)并分别构建该树,但事实并非如此。取消编组时,它将提供正确的节点树,但是重新编组时,它将产生以下yaml,其中包含yaml.Node公开的所有字段。可悲的是我们不能走这条路,必须找到另一条路。

version: "1"
type: verbose
kind: bfr
applications:
    kind: 2
    style: 0
    tag: '!!seq'
    value: ""
    anchor: ""
    alias: null
    content:
    -   #  First app
name: app1
        kind: nodejs
        path: app1
        exec:
            platforms: k8s
            builder: test
    headcomment: ""
    linecomment: ""
    footcomment: ""
    line: 9
    column: 3
Run Code Online (Sandbox Code Playgroud)

现在,我们可以忽略结构中yaml.Nodes的第一个问题和程序错误(位于gopkg.in/yaml.v3 v3.0.0-20190409140830-cdc409dda467上),我们可以开始处理程序包公开的Nodes。不幸的是,没有可以轻松添加节点的抽象,因此用途可能会有所不同,并且标识节点可能会很麻烦。反思可能会对您有所帮助,因此我将其作为练习留给您。

您会发现注释spew.Dump以一种不错的格式转储了整个节点Tree,这有助于在将Nodes添加到源代码树时进行调试。

当然,您也可以删除节点,您只需要确定需要删除的特定节点即可。您只需确保删除父节点(如果它们是图或序列)即可。

type VTS struct {
    Version string       `yaml:"version" json:"version"`
    Types   string       `yaml:"type" json:"type"`
    Kind    string       `yaml:"kind,omitempty" json:"kind,omitempty"`
    Apps    yaml.Node `yaml:"applications,omitempty" json:"applications,omitempty"`
}
Run Code Online (Sandbox Code Playgroud)

生产yaml

version: 1
type: verbose
kind: bfr


# my list of applications
applications:
-   #  First app
name: app1
    kind: nodejs
    path: app1
    exec:
        platforms: k8s
        builder: test
-   # Second app
name: app2
    kind: golang
    path: app2
    exec:
        platform: dockerh
        builder: test
Run Code Online (Sandbox Code Playgroud)