ansible笔记(32):过滤器(二)

栏目: 服务器 · 发布时间: 5年前

内容简介:所属分类:ansible
  • A+

所属分类:ansible 运维技术

在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。

ansible系列博文直达链接:ansible轻松入门系列

"ansible系列"中的每篇文章都建立在前文的基础之上,所以, 请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。

之前已经总结过一些过滤器的用法,这篇文章我们继续来认识一些其他的过滤器。

在实际工作中,经常需要调用别人的接口,别人的接口会返回我们需要的数据,有时候,返回的数据就是json格式的,比如,公司为某些域名配置了CDN,当我们需要分析这些域名的访问日志时,则需要从CDN厂商获取到对应的日志,通常情况下,CDN服务商会暴露一个接口给我们,我们调用这个接口,即可获取到对应域名的日志列表,然后根据列表下载所有的日志,从而达到我们的目的,我们先一起来看一段示例数据,如下数据是我调用了CDN厂商接口后,返回的一段json格式的数据,如下

{"logs":[{"domainName":"asia1.cdn.test.com","files":[{"dateFrom":"2018-09-05-0000","dateTo":"2018-09-05-2359","logUrl":"http://log.testcd.com/log/zsy/asia1.cdn.test.com/2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz?wskey=XXXXX5a","fileSize":254,"fileName":"2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz","fileMd5":"error"}]},{"domainName":"image1.cdn.test.com","files":[{"dateFrom":"2018-09-05-2200","dateTo":"2018-09-05-2259","logUrl":"http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz?wskey=XXXXX1c","fileSize":10509,"fileName":"2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz","fileMd5":"error"},{"dateFrom":"2018-09-05-2300","dateTo":"2018-09-05-2359","logUrl":"http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz?wskey=XXXXXfe","fileSize":5637,"fileName":"2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz","fileMd5":"error"}]}]}

这段json数据并没有很高的可读性,因为它并没有进行任何缩进和换行,如果你想让这段数据有更高的可读性,则可以将这段数据所在的文件当做变量文件引入到playbook中,然后输出对应的变量即可,示例如下

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - include_vars:
      file: "/testdir/ansible/wsCdnLogList"
      name: testvar
  - debug:
      msg: "{{ testvar }}"

如上例所示,"/testdir/ansible/wsCdnLogList"就是上述json数据所在的文件,它位于ansible主机中,我们使用include_vars模块,将此文件当做变量文件引入了playbook中,在总结变量时我们提到过,变量文件的格式可以是yaml格式的,也可以是json格式的,上例就是将json格式的数据文件当做变量文件使用的,并且,将此文件的json数据赋值给了testvar变量,然后使用debug模块输出了testvar变量的值,那么,我们执行一下上例的playbook,可以发现,json数据已经被格式化为了有一定可读性的json文本输出在了控制台中,输出信息如下:

TASK [debug] ********************************************************************
ok: [test70] => {
    "msg": {
        "logs": [
            {
                "domainName": "asia1.cdn.test.com",
                "files": [
                    {
                        "dateFrom": "2018-09-05-0000",
                        "dateTo": "2018-09-05-2359",
                        "fileMd5": "error",
                        "fileName": "2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz",
                        "fileSize": 254,
                        "logUrl": "http://log.testcd.com/log/zsy/asia1.cdn.test.com/2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz?wskey=XXXXX5a"
                    }
                ]
            },
            {
                "domainName": "image1.cdn.test.com",
                "files": [
                    {
                        "dateFrom": "2018-09-05-2200",
                        "dateTo": "2018-09-05-2259",
                        "fileMd5": "error",
                        "fileName": "2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz",
                        "fileSize": 10509,
                        "logUrl": "http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz?wskey=XXXXX1c"
                    },
                    {
                        "dateFrom": "2018-09-05-2300",
                        "dateTo": "2018-09-05-2359",
                        "fileMd5": "error",
                        "fileName": "2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz",
                        "fileSize": 5637,
                        "logUrl": "http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz?wskey=XXXXXfe"
                    }
                ]
            }
        ]
    }
}

其实,json是yaml的子集,yaml是json的超集,yaml格式的数据和json格式的数据是可以互相转换的,所以,对于ansible来说,当我们把上例中的json数据文件当做变量文件引入时,就好像引入了一个我们定义好的yaml格式的变量文件一样,对于ansible来说是没有区别的,而且,即使在变量文件中使用yaml格式定义了变量,在使用debug模块输出变量信息时,ansible也会自动将yaml格式的数据转化为json格式后进行输出,细心如你一定已经在前面的文章中发觉到这一点了,那么,我们把上述json数据转换成yaml的格式,同时列出上述数据的json格式与yaml格式,你可以根据自己的使用习惯,选择阅读哪种格式的数据,以便你能够更好的理解这段数据的含义,yaml格式如下

logs:
-   domainName: asia1.cdn.test.com
    files:
    -   dateFrom: 2018-09-05-0000
        dateTo: 2018-09-05-2359
        fileMd5: error
        fileName: 2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz
        fileSize: 254
        logUrl: http://log.testcd.com/log/zsy/asia1.cdn.test.com/2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz?wskey=XXXXX5a
-   domainName: image1.cdn.test.com
    files:
    -   dateFrom: 2018-09-05-2200
        dateTo: 2018-09-05-2259
        fileMd5: error
        fileName: 2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz
        fileSize: 10509
        logUrl: http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz?wskey=XXXXX1c
    -   dateFrom: 2018-09-05-2300
        dateTo: 2018-09-05-2359
        fileMd5: error
        fileName: 2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz
        fileSize: 5637
        logUrl: http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz?wskey=XXXXXfe

从上述信息可以看出,cdn厂商返回的j数据是一个日志列表,这个日志列表中一共有两个对象,对象的属性有"domainName"和 "files",很明显,cdn厂商将日志按照域名进行了划分,返回了对应域名下的所有日志, "files"属性是一个列表,列表中列出了对应域名中的所有日志文件的信息,第一个域名的files列表中只有一个日志文件,第二个域名的files列表中一共有两个日志文件。

此刻,如果我们想要获取到整个列表中的所有日志文件的logUrl,我们该怎么办呢?

没错,聪明如你一定想到了,我们可以通过with_subelements循环,获取到当前整个大列表中的所有日志的logUrl属性,前文已经总结过了with_subelements的用法,此处不再赘述,如果你忘记了它的用法,请回顾前文,此处直接写出示例,如下:

  tasks:
  - include_vars:
      file: "/testdir/ansible/wsCdnLogList"
      name: testvar
  - debug:
      msg: "{{ item.1.logUrl }}"
    with_subelements:
    - "{{testvar.logs}}"
    - files

其实,除了使用with_subelements,我们还有另外一种方法,就是使用过滤器,有一个名为json_query的过滤器,可以帮助我们解决上述问题。

我们先来看几个关于json_query的小示例,等熟悉了json_query过滤器以后,再回过头来通过json_query解决上面的问题,小示例如下

假设我们现在有一段简单的json数据,如下:

{
  "users": [
    {
      "name": "tom",
      "age": 18
    },
    {
      "name": "jerry",
      "age": 20
    }
  ]
}

上述json数据的yaml格式如下:

---
users:
- name: tom
  age: 18
- name: jerry
  age: 20

从上述示例可以看出,一共有两个用户,两个用户的名字分别为tom和jerry,年龄分别为18和20,如果我们想要通过json_query过滤器获取到上述json中的所有user的name,则可以使用如下方法:

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - include_vars:
      file: "/testdir/ansible/testvarfile"
      name: testvar
  - debug:
      msg: "{{ testvar | json_query('users[*].name') }}"

上例的"/testdir/ansible/testvarfile"文件就是上述示例数据所在的文件,它位于ansible主机中,我们将这段数据当做变量赋值给了testvar变量,之后,使用json_query过滤器对这个变量进行了处理,json_query('users[*].name')表示找到users列表中所有元素的name属性,执行上例playbook后,debug模块的输出信息如下:

TASK [debug] *****************************************
ok: [test70] => {
    "msg": [
        "tom",
        "jerry"
    ]
}

如我们所愿,我们找到了所有用户的name属性,它们被放在了一个列表中展示了出来,你一定已经会举一反三了,查找user列表中的所有元素的age属性的值,则可以使用如下方法

  - debug:
      msg: "{{ testvar | json_query('users[*].age') }}"

我们再来看一段数据,这段数据位于ansible主机的/testdir/ansible/testvarfile1文件中,此处不再将如下yaml数据转换成json格式,在如下示例中,两种格式没有任何区别,示例数据如下

---
test:
  users:
  - name: tom
    age: 18
    hobby:
    - Skateboard
    - VideoGame
  - name: jerry
    age: 20
    hobby:
    - Music

从上述示例可以看出,一共有两个用户,除了姓名和年龄属性,每个用户还有爱好属性,爱好属性是一个列表,如果,我们想要获取到所有的爱好,改怎样使用json_query来完成呢?示例如下:

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - include_vars:
      file: "/testdir/ansible/testvarfile1"
      name: testvar
  - debug:
      msg: "{{ testvar | json_query('test.users[*].hobby[*]') }}"

没错,上例表示,获取到users列表中所有hobby列表的所有项,正如你所看到的,当数据结构中存在列表时,我们可以使用"列表名[*]"获取到列表下面的所有项,那么,我们来执行一下上例的playbook,执行后debug模块输出结果如下:

TASK [debug] *************************************
ok: [test70] => {
    "msg": [
        [
            "Skateboard",
            "VideoGame"
        ],
        [
            "Music"
        ]
    ]
}

返回给我们的数据是一个json列表,这个列表中嵌套了两个列表,正是上述示例数据中两个用户的"爱好列表",如果你想要将上例嵌套的列表拉平后输出,则可以使用之前总结的循环进行操作,此处不再赘述。

在上述示例中,我们都是获取到users列表中的所有用户的信息,但是如果我们想要根据条件获取到某个用户的某些信息,该怎么办呢?比如,我想要获取到tom的爱好,则可以使用如下方法:

  tasks:
  - include_vars:
      file: "/testdir/ansible/testvarfile1"
      name: testvar
  - debug:
      msg: "{{ testvar | json_query('test.users[?name==`tom`].hobby[*]') }}"

上例中,json_query('test.users[?name==`tom`].hobby[*]')表示只查找users列表中name属性等于tom的hobby信息,你肯定发现了,上例中,我们使用了"反引号"将tom引起来了,这是因为当你在添加查询条件时,对需要为对应的值添加引号,但是,上例中msg的值的外侧已经存在一对双引号,双引号内又有一对单引号,所以,为了不让引号之间互相冲突,此处使用反引号将tom引起,除了使用反引号,也可以如下方法,实现相同的效果:

  tasks:
  - include_vars:
      file: "/testdir/ansible/testvarfile1"
      name: testvar
  - debug:
      msg: "{{ testvar | json_query(querystring) }}"
    vars:
      querystring: "test.users[?name=='tom'].age"

如上例所示,我们在debug任务中使用vars关键字定义了一个只有当前debug任务能够使用的变量,从而避免了多层引号嵌套时所产生的冲突问题。

我们也可以同时获取到用户的姓名、年龄两个属性的值,当需要同时获取多个属性值时,需要通过键值对的方式调用属性,示例如下:

  tasks:
  - include_vars:
      file: "/testdir/ansible/testvarfile1"
      name: testvar
  - debug:
      msg: "{{ testvar | json_query('test.users[*].{uname:name,uage:age}') }}"

如上例所示 ,json_query('test.users[*].{uname:name,uage:age}')表示找到users列表中所有用户的name值和age值,如你所见,uname和uage是我自定义的名称,你也可以随意定义,但是,name和age必须用数据中的属性的键名对应,执行上例playbook后,debug模块输出信息如下:

TASK [debug] **************************************
ok: [test70] => {
    "msg": [
        {
            "uage": 18,
            "uname": "tom"
        },
        {
            "uage": 20,
            "uname": "jerry"
        }
    ]
}

如上所示,用户的姓名和年龄都按照我们定义的方式输出了。

好了,说了这么多,json_query过滤器的用法你肯定已经掌握了,所以,我们回过头来,使用json_query来解决一下文章最开始的问题,我们的目标是,使用json_query过滤器找到cdn厂商返回的json数据中的所有日志的logUrl,那么我们可以怎么编写playbook呢?示例如下 :

---
- hosts: test70
  remote_user: root
  gather_facts: no
  vars_files:
  - /testdir/ansible/wsCdnLogList
  tasks:
  - debug:
      msg: "{{item}}"
    with_items: "{{ logs | json_query('[*].files[*].logUrl') }}"

上例playbook的执行效果我就不粘贴了,快动手试试吧。

希望这篇文章能够帮助到你,加油~

我的微信公众号

关注"实用运维笔记"微信公众号,当博客中有新文章时,可第一时间得知哦~


以上所述就是小编给大家介绍的《ansible笔记(32):过滤器(二)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Lean Analytics

Lean Analytics

Alistair Croll、Benjamin Yoskovitz / O'Reilly Media / 2013-3-18 / USD 29.99

If you're involved with a startup, analytics help you find your way to the right product and market before the money runs out. But with a flood of information available, where do you start? This book ......一起来看看 《Lean Analytics》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具