Symais
Symais

Reputation: 27

Parsing in block a YAML File

I have a yaml file that is currently written as:

host: hostname   
resource:
      File:
        title: "file"
        containment_path:
        - Test
        - Test::Value
        tags:
        - file
        failed: false
        skipped: false
        corrective_change: false
      Exec:
        title: Exec
        containment_path:
        - Test
        - Value::Test
        tags:
        - exec
        failed: true
        skipped: false
        corrective_change: false

Then the values in resource like File and Exec can be different each time
I use this structure to parse my YAML data

    type YamlResource struct {
        Host                 string        `yaml:"host"`
        Resource             []Resource    `yaml:"resource"`
    }
    
    type Resource struct {
        ContainmentPath      string        `yaml:"containment_path"`
        Skipped              bool          `yaml:"skipped"`
        Failed               bool          `yaml:"failed"`
    }

func ScanningYAMLModulesStatus(filename string) (YamlModulesStatus, error) {
    
    f, err := os.Open(filename)
    if err != nil {
        fmt.Println("Error reading YAML ", filename, ": ", err)
    }
    defer f.Close()

    scanner := bufio.NewScanner(f)
    isRecord := false
    data := ""
    for scanner.Scan() {
        line := scanner.Text()
        if strings.Contains(scanner.Text(), "host:") {
            data += line + "\n"
        }
        if strings.Contains(scanner.Text(), "resource:") {
            isRecord = true
        }
        if strings.Contains(scanner.Text(), "corrective_change:") {
            break
        }
        if isRecord {
            data += line + "\n"
        }
    }

    if err := scanner.Err(); err != nil {
        fmt.Println("Error scanning YAML ", filename, ": ", err)
    }

    var ConfigResource YamlResource
    if err = yaml.Unmarshal([]byte(data), &ConfigResource); err != nil {
        fmt.Println("Error parsing YAML ", filename, ": ", err)
    }
    return ConfigResource, err 
}

I get this error and I would like to parse the resources by block because I have a lot of data such as a File block, an Exec block and I can't modify my YAML file
I use package "gopkg.in/yaml.v2"

line 3: cannot unmarshal !!map into []main.YamlResource

How can I do this in Go, to parse File, Exec and others ?
Thanks

Upvotes: 0

Views: 375

Answers (1)

Shailesh Suryawanshi
Shailesh Suryawanshi

Reputation: 1270

Looks like the to be unmarshalled struct definition is mismatching as suggested in comments.

I have refactored the code to correct struct definitions. The working code can be found here on playground. Link

type YamlResource struct {
    Host     string   `yaml:"host"`
    Resource Resource `yaml:"resource"`
}

type Resource struct {
    File File `yaml:"File"`
    Exec Exec `yaml:"Exec"`
}

type Exec struct {
    ContainmentPath []string `yaml:"containment_path"`
    Skipped         bool     `yaml:"skipped"`
    Failed          bool     `yaml:"failed"`
}

type File struct {
    ContainmentPath []string `yaml:"containment_path"`
    Skipped         bool     `yaml:"skipped"`
    Failed          bool     `yaml:"failed"`
}

Upvotes: 2

Related Questions