web-dev-qa-db-fra.com

Modifier le fichier yaml existant et ajouter de nouvelles données et commentaires

J'ai récemment vu que le go yaml lib a une nouvelle version (V3)

avec les capacités nœuds (ce qui, à mon avis, est une fonctionnalité de tueur :)) qui peut aider beaucoup à modifier les yamls sans changer la structure du fichier

Mais comme il est assez récent (de la semaine dernière), je n'ai pas trouvé de documents utiles et d'exemples pour le contexte dont j'ai besoin (ajouter un nouvel objet/nœud et conserver la structure du fichier identique sans supprimer les commentaires, etc.)

ce dont j'ai besoin c'est de manipuler le fichier yaml

par exemple

disons que j'ai ce fichier yaml

version: 1
type: verbose
kind : bfr

# my list of applications
applications:
  - name: app1
    kind: nodejs
    path: app1
    exec:
      platforms: k8s
      builder: test

Maintenant, j'ai un objet json (par exemple avec app2) Que je dois insérer dans le fichier existant

[

    {
        "comment: "Second app",
        "name": "app2",
        "kind": "golang",
        "path": "app2",
        "exec": {
            "platforms": "dockerh",
            "builder": "test"
        }
    }
]

et je dois l'ajouter au fichier yml après la première application (les applications sont un tableau d'applications)

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

est-il possible d'ajouter à partir du fichier yaml le nouvel objet json? supprimer également les

J'ai également trouvé ce blog https://blog.ubuntu.com/2019/04/05/api-v3-of-the -yaml-package-for-go-is-available

Ce sont les types qui représentent l'objet

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

mise à jour

après avoir testé la solution fournie par wiil7200 j'ai trouvé 2 problèmes

J'utilise à la fin l'écrire dans le fichier err = ioutil.WriteFile("output.yaml", b, 0644)

Et la sortie yaml a 2 problèmes.

  1. Le tableau de l'application commence à partir des commentaires, il doit commencer par le nom

  2. Après l'entrée name, la propriété kind et toutes les autres après ne sont pas alignées sur la name

une idée de comment résoudre ces problèmes? en ce qui concerne le problème comments, disons que je l'ai obtenu d'une autre propriété et non du json (si cela le rend plus simple)

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
11
Rayn D

Vous pouvez créer un nouveau nœud et l'ajouter directement au contenu, sans supprimer le nœud précédent. L'exemple suivant illustre ce point:

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
`
)

type Application struct {
    Name string `yaml:"name,omitempty" json:"name,omitempty"`
    Kind string `yaml:"kind,omitempty" json:"kind,omitempty"`
    Path string `yaml:"path,omitempty" json:"path,omitempty"`
    Exec struct {
        Platforms string `yaml:"platforms,omitempty" json:"platforms,omitempty"`
        Builder   string `yaml:"builder,omitempty" json:"builder,omitempty"`
    } `yaml:"exec,omitempty" json:"exec,omitempty"`
}

func newApplicationNode(
    name string,
    kind string,
    path string,
    platforms string,
    builder string,
    comment string) (*yaml.Node, error) {

    app := Application{
        Name: name,
        Kind: kind,
        Path: path,
        Exec: struct {
            Platforms string `yaml:"platforms,omitempty" json:"platforms,omitempty"`
            Builder   string `yaml:"builder,omitempty" json:"builder,omitempty"`
        }{platforms, builder},
    }
    marshalledApp, err := yaml.Marshal(&app)
    if err != nil {
        return nil, err
    }

    node := yaml.Node{}
    if err := yaml.Unmarshal(marshalledApp, &node); err != nil {
        return nil, err
    }
    node.Content[0].HeadComment = comment
    return &node, nil
}

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

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

    newApp, err := newApplicationNode("app2", "golang", "app2", "dockerh",
        "test", "Second app")
    if err != nil {
        log.Fatalf("error: %v", err)
    }

    appIdx := -1
    for i, k := range yamlNode.Content[0].Content {
        if k.Value == "applications" {
            appIdx = i + 1
            break
        }
    }

    yamlNode.Content[0].Content[appIdx].Content = append(
        yamlNode.Content[0].Content[appIdx].Content, newApp.Content[0])

    out, err := yaml.Marshal(&yamlNode)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(out))
}

De toute évidence, au lieu de suivre la voie hacky comme je l'ai fait dans newApplicationNode, vous pouvez dissocier correctement votre JSON. Cependant, comme indiqué dans les réponses précédentes, il est important de noter que la clé et la valeur réelle se trouvent dans les index suivants à l'intérieur de Content, vous devez donc en tenir compte lors de la modification du document. (par exemple, recherchez la clé applications mais considérez ensuite l'index suivant (appIdx = i + 1 dans mon exemple) pour son contenu.

J'espère que cela pourra aider!

0
nettrino