【问题标题】:Validate yaml schema with golang (semantic check)使用 golang 验证 yaml 架构(语义检查)
【发布时间】:2018-09-01 17:24:43
【问题描述】:

我们有需要读取具有特定结构的 YAML 文件的工具。当我们得到 YAML 文件时,我们需要知道是否

  1. 根据某些准则检查 YAML 文件是否有效 - 语义检查
  2. 语法错误在哪里

例如,这是我们需要解决的验证示例

 _version:  {required: true}
   id: {required: true, pattern: '/^[A-Za_\-\.]+$/'}   
   release-version: {required: true}
   type:   

   builds:
     type:seq
     sequence:
       -type:map
     mapping:
        name:{required: true, unique: true, pattern: '/^[A-Za-z0-3_\-\.]+$/'}
        params: 
          type: map
          mapping: { =: {type: any} } 

映射是键值对象
seq 可以有多个构建
输入任何是和键值

我们使用这个开源来解析yaml https://github.com/go-yaml/yaml

一个想法(这很好)是转换为 json,如下所示,通过将文件转换为 json 并验证它是否有库支持它,在我的上下文中的任何示例都会非常有帮助 https://github.com/xeipuuv/gojsonschema

但不确定我如何处理

Type map
Type seq

【问题讨论】:

  • 为什么是docker 标签?
  • @BMitch - 我相信 docker 和 k8s 有相同的任务,验证 yaml 架构以进行部署,不是吗?所以也许我可以使用相同的想法......

标签: validation go schema yaml dockerfile


【解决方案1】:

您可以使go-yamljsonschema 一起工作。看到这个问题:https://github.com/santhosh-tekuri/jsonschema/issues/5

简而言之:

  1. 根据this issue,创建一个生成兼容输出类型的自定义 yaml 解析器。
  2. 使用该自定义解析器将 yaml 解析为 interface{}
  3. 使用jsonschema.ValidateInterface 进行验证。

(一旦 yaml.v3 发布,自定义解组器应该可以替换为配置选项)

我最初使用公认答案的方法解析为一个结构,然后编写代码来手动验证该结构是否符合我的规范。这很快就变得非常丑陋 - 上述方法允许一个干净的单独规范和可靠的验证。

【讨论】:

    【解决方案2】:

    这是你可以尝试的。

    按照预期的 yaml 数据的形状建模一个结构体:

    type Config struct {
            Version struct {
                    Required bool
            }
            ID struct {
                    Required bool
                    Pattern string
            }
            ReleaseVersion struct {
                    Required bool
            }
            Type interface{}
            Builds struct {
                    Type []interface{} `yaml:"type"`
                    Sequence struct {
                            Type string
                    }
                    Mapping struct {
                            Name map[string]interface{}
                            Params struct {
                                    Type string `yaml:"type"`
                                    Mapping struct {
                                            To map[string]string `yaml:"="`
                                    }
                            }
                    } `yaml:"mapping"`              
            }
    }
    

    添加了yaml标志yaml:"somefield"来标记我们感兴趣的数据的yaml的字段名称。

    还有许多未知/未确定类型的字段可以声明为空接口(interface{}),或者如果您想“强制”底层表单是键值对象,您可以将其声明为map[string]interface{}或其他结构。

    然后我们将 yaml 数据解组到结构中:

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

    由于我们将字段建模为匿名结构或映射,因此我们可以通过检查特定字段与 nil 的相等性来测试特定字段是否具有“键值”值。

    // Mapping is a key value object
    if (Mapping != nil) {
            // Mapping is a key-value object, since it's not nil.
    }
    
    
    // type any is and key value
    // Mapping.To is declared with map[string]string type
    // so if it's not nil we can say there's a map there.
    if (Mapping.To != nil) {
            // Mapping.To is a map
    }
    

    在编组/解组中,映射和结构是可以互换的。结构的好处是您可以提前预定义字段的名称,同时将其解组到映射时,您将不清楚键是什么。

    【讨论】:

    • 感谢您的回答!几个问题,如果您可以将答案添加到您的答案中,那就太好了 :),1. 像这样使用 jsonschema 是否更好,即转换为 json 并验证? 2. yaml:"type" yaml:"=" 等所有这些注释的作用是什么,它是如何工作的? 3. golang中interface{}map[string]interface{}是什么类型? 4. 你知道k8sdocker compose 正在做什么来解决这个问题吗?两者都有我确定需要验证的yaml 模式?非常感谢!!!
    • 是否要转换为 JSON 取决于您/您的团队。一般来说,JSON 当然更容易解析。所有其他问题都添加到答案中,除了关于 docker 的最后一个我没有答案的问题,也许最好在另一个问题中提出。
    • 非常感谢 1+!我找到了这个 github.com/docker/libcompose/blob/master/config/schema.go 和这个 github.com/docker/compose/blob/master/compose/config/… ,你觉得,如果你需要按照你选择的方式来做,为了简单而不至死胡同?
    • 很抱歉,我认为这超出了问题的范围。
    • 谢谢,我回答了这个问题,我的问题是如果你需要做这样的任务,你会走哪条路:)?
    猜你喜欢
    • 1970-01-01
    • 2021-08-03
    • 2011-06-18
    • 2016-02-11
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多