Friday, November 19, 2021

[SOLVED] Checking if string from golang file exists in yaml file

Issue

I am rather new to working with yaml and golang. Currently, I am creating a golang program that parses an rpm package to check for subsystem dependencies. It extends the go-rpmutils library.

So far this is the code I have within my main function to handle conditions:

func main() {
    // Parse the rpm
    rpm, err := rpmutils.ReadRpm("file.rpm")
    if err != nil {
        panic(err)
    }

    // Get RPM Deps
    dependencies, err := rpm.Header.GetStrings(rpmutils.REQUIRENAME)
    if err != nil {
        panic(err)
    }

    // Check for specific dep condition
    for _, p := range dependencies {
        if strings.HasPrefix(p, "prefix1") && p != "string-including-prefix1" {
            fmt.Printf("\t%s\n", p)
            defer os.Exit(1)
        }
    }
}

I am able to output the dependencies but want to set up several if else conditions for when specific subsystem dependencies exist.

In a separate yaml file, I have:

allowed-deps:
    -dep1
    -dep2
    -dep3

third-party-deps:
    -dep4
    -dep5
    -dep6

internal-deps:
    -dep7
    -dep8
    -dep9

I'd like to compare the value of var p from the for loop with the values in the yaml file. So for example:

  • if p only equals values from allowed-deps, print "successfully built rpm" and do not prompt os.Exit(1)
  • if p equals any of the third-party-deps, print "err msg for third-party deps" and os.Exit(1)
  • if p equals any internal-deps, print "another err mssg" and os.Exit(1)

How can I go about doing this?


Solution

You can use a YAML package (like https://github.com/go-yaml/yaml), load your file into a variable and check it on every step in the ifs that you propose. I would use maps as it seems that you will be checking very frequently the sets.

Here you have a simple example that I made using that package so you can see how to unmarshal your file, convert into maps, and check the maps: https://play.golang.org/p/t1GhUPvAQNQ

package main

import (
    "fmt"
     "github.com/go-yaml/yaml"
)

const str = `
allowed-deps:
    - dep1
    - dep2
    - dep3

third-party-deps:
    - dep4
    - dep5
    - dep6

internal-deps:
    - dep7
    - dep8
    - dep9
`

type MyYAML struct {
    AllowedDeps    []string `yaml:"allowed-deps"`
    ThirdPartyDeps []string `yaml:"third-party-deps"`
    InternalDeps   []string `yaml:"internal-deps"`
}

func main() {
    var a MyYAML
    err := yaml.Unmarshal([]byte(str), &a)
    if err != nil {
        panic(err)
    }

    // Build a map for every section.
    allowedDeps    := map[string]struct{}{}
    thirdPartyDeps := map[string]struct{}{}
    internalDeps   := map[string]struct{}{}

    for _, dep := range a.AllowedDeps {
        allowedDeps[dep] = struct{}{}
    }
    for _, dep := range a.ThirdPartyDeps {
        thirdPartyDeps[dep] = struct{}{}
    }
    for _, dep := range a.InternalDeps {
        internalDeps[dep] = struct{}{}
    }

    // Some checking examples.
    if _, ok := allowedDeps["dep1"]; ok {
        fmt.Println("dep1 found")
    }
    if _, ok := thirdPartyDeps["dep1"]; ok {
        fmt.Println("dep1 found")
    }
    if _, ok := internalDeps["dep8"]; ok {
        fmt.Println("dep8 found")
    }

}


Answered By - NicoGonzaMu