YAML文件技巧

YAML文件技巧

YAML是Ansible,k8s,Docker等软件大量使用的文件格式,也是当今最流行的配置文件格式。今天就聊聊几个在写YAML文件时注意的小技巧或者问题

请尽量参考官方的YAML spec,目前是1.2版 https://yaml.org/spec/1.2/spec.html

Lint

和Python,Java等编程语言一样,YAML也有对应的lint工具帮大家检查文件的语法和结构问题。个人建议一定要把lint的检查部署到CI中。在本地开发,你也可以:

# all.yml
- tabitha:
    name: Tabitha Bitumen
    job: Developer
    skills:
      - lisp
      - fortran
      - erlang
    - test

执行的效果。

(yaml) ➜  yaml-tips yamllint all.yml
all.yml
  10:5      error    syntax error: expected <block end>, but found '-' (syntax)
  10:11     error    no new line character at the end of file  (new-line-at-end-of-file)
(yaml) ➜  yaml-tips

Space vs Tab

对于代码缩进用空格还是Tab,这个一直都有争论。但是由于目前的IDE都可以设置tab键的空格个数,并且可以根据文件的不同类型而不同。所以基本争议主要在使用几个空格的问题上。

我个人本身认为自己不是程序员,毕竟不是每天都写代码,偶尔写写Python和Ansible,我的VS Code里设置的是Python 4空格缩进,Ansible(YAML)是2空格缩进,这基本也是官方spec推荐的。

缩进的这个问题,最关键的我个人认为是要和team成员沟通好,大家达成一致最好,剩下的就交给IDE和lint工具即可。

如果文件里的缩进出现不一致的情况,lint工具一般会帮我们指出。

(yaml) ➜  yaml-tips yamllint all.yml
all.yml
  7:9       error    wrong indentation: expected 6 but found 8  (indentation)
(yaml) ➜  yaml-tips

行最大的长度

一行的最大长度规定也不是死的,之所以很多lint检查工具都会检查行最大长度,主要是问了提高代码的可阅读性,如果一行太长,则需要拉动左右的滑动条进行代码阅读,无疑会影响代码阅读的体验。

yamllint设置的默认行最大长度是80个字符,如果超过了,则会报错。

(yaml) ➜  yaml-tips yamllint all.yml
all.yml
  7:81      error    line too long (86 > 80 characters)  (line-length)

(yaml) ➜  yaml-tips

80个人觉得有点短,特是大家现在的显示器都很大,分辨率很高。和Python一样,我个人推荐**>=120**个字符每行。 这个可以修改yamllint的rule规则。

但是即使设置了120个字符,个别情况下,我们的行的字符可能超过这个长度,这时候就要考虑换行了。基本有三种情况

include_newlines: |
  exactly as you see
  will appear these three
  lines of poetry

结果就是 (每一行最后包括最后一行都会有换行) 'exactly as you see\nwill appear these three\nlines of poetry\n'

fold_newlines: >
  this is really a
  single line of text
  despite appearances

结果是(只有最后 一行有换行,其它以空格连接) 'this is really a single line of text despite appearances\n'

fold_newlines_without_newlines_at_the_end: >-
  this is really a
  single line of text
  despite appearances

结果是(和上一个不同之处在于最后一行没有换行) 'this is really a single line of text despite appearances'

Anchors and References

这个可能用的不多,但是真正需要的时候确实能你给解决大的问题。

有时候在YAML文件里我们可能需要定义复杂的一些数据结构,这个结构中可能有部分的key-value存在重复引用的问题。举个例子

比如下面这个prefix_list的值实际是一样,存在重复。

ip_prefix_list:
  - name: permit_func_xyz
    prefix_list:
      - seq: 10
        prefix: 192.168.1.0/24
      - seq: 20
        prefix: 192.168.2.0/24
      - seq: 30
        prefix: 192.168.3.0/24
  - name: permit_func_abc
    prefix_list:
      - seq: 10
        prefix: 192.168.1.0/24
      - seq: 20
        prefix: 192.168.2.0/24
      - seq: 30
        prefix: 192.168.3.0/24

通过YAML的anchors reference语法,可以改成下面这样,类似定义一个变量,下面去引用

prefix_list_value: &prefix_list_value
  - seq: 10
    prefix: 192.168.1.0/24
  - seq: 20
    prefix: 192.168.2.0/24
  - seq: 30
    prefix: 192.168.3.0/24

ip_prefix_list:
  - name: permit_func_xyz
    prefix_list: *prefix_list_value
  - name: permit_func_abc
    prefix_list: *prefix_list_value

更重要的是,这个功能不止可以做到这个,还可以实现部分变量的共享和引用,比如:

foo:
  <<: &anchor
    K1: "One"
  K2: "Two"

bar:
  <<: *anchor
  K3: "Three"

最终的结果会是

{
  'bar': {
    'K1': 'One', 
    'K3': 'Three'
  },
  'foo': {
    'K1': 'One', 
    'K2': 'Two'
  }
}

Validator

当你不确定自己的YAML格式(数据层面)是否有问题的时候,最简单的办法就是用检查工具,这种工具有很多。

另外因为YAML和JSON有着天然的密切关系,可以通过工具(比如python pyyaml)把YAML文件转成JSON,对比一下,也是不错的办法。

Discussion