使用 Ansible 与 REST API

您可能已经使用 Web 浏览器或 curl 查询过 API,但 Ansible 被忽视的一个能力是它能够很好地利用 API 作为任何 playbook 的一部分。
53 位读者喜欢这篇文章。
Looking at a map

opensource.com

Ansible 是一个顶级的开源项目,表面上,它提供了一种简单的方法来标准化您现有的自动化,并允许它在多个主机上并行运行,并且它非常成功地做到了这一点。然而,实际上,Ansible 有能力扩展您现有自动化所做的事情,以整合其他系统,并真正简化您日常例行工作各个方面的任务。

这种能力始于 Ansible 中包含的 collectionsroles 以及通过 Ansible Galaxy 分发的所有第三方实用程序。您可能已经使用 Web 浏览器或 curl 查询过 API,但 Ansible 被忽视的一个能力是它能够很好地利用 API 作为任何 playbook 的一部分。 这非常有用,因为内部和全球互联网上构建和部署的 REST API 的数量呈指数级增长。 甚至有一个 public-apis GitHub 仓库 列出了数百个免费 API,涵盖十几个类别,以供参考。

 

 

一个基本的 API playbook

实际上,这归结为 Ansible 中的一些关键核心功能,这些功能通过一个特定的内置任务 _uri_ 很好地公开。 在这篇文章中,我将通过一个相当简单的例子来说明如何调用 REST API,并使用该调用的数据来决定下一步该做什么。 这适用于 Ansible 2.9 及更高版本。 在更高版本(特别是 v4)中,我们使用的模块需要加上 _ansible.builtin_ 前缀,例如 _ansible.builtin.set_fact_ 而不是仅 _set_fact_。

要开始使用,您需要一个基本的 playbook 来构建。 在本例中,您只使用本地调用,因此不需要超级用户权限。

首先,创建这个 YAML 文件来建立一个工作基线

---
- name: Using a REST API
  become: false
  hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: “Let’s call an API”

这是运行后的输出

% ansible-playbook using-a-rest-api.yml

PLAY [Using a REST API] *********************************************************************************************

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
    "msg": "“Let’s call an API”"
}

PLAY RECAP **********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

调用 API

要调用实际的 API,您可以使用 _uri_ 模块。 这里有两个例子。 第一个是 GET 请求,第二个是带有参数的 POST 请求,以显示不同的可用选项。

---
- name: Everyone loves a good Chuck Norris joke
  uri:
    url: https://api.chucknorris.io/jokes/random
    method: GET

- name: Login to an API
  uri:
    url: https://auth.example.com/oauth/access_token
    method: POST
    body_format: json
    body:
      name: your_username
      password: your_password
      client_id: YOUR_CLIENT_ID
      access_token: ACCESS_TOKEN
      connection: CONNECTION
      scope: SCOPE

我使用第一个 API 用于本文的其余部分,以展示如何使用返回的数据。 问题是,您如何收集返回的数据,以及它的外观是什么?

[ 提升您的自动化专业知识。 获取 Ansible 清单: 迁移到 Red Hat Ansible Automation Platform 2 的 5 个理由 ]

要收集在 Ansible 中运行的任何任务的输出,您可以使用 _register_ 属性,然后您可以使用 _debug_ 任务来显示原始数据。 在使用 _uri_ 调用的 API 的情况下,所有输出都放在结果的 .json. Subsection 下。 _uri_ 命令和其他输出也位于该顶层。 这些可用于通过查看状态等其他数据字段来确保 API 调用有效。

这是您必须添加到原始 playbook 中的两个任务,以便将 API 调用添加到混合中,以便稍后执行某些操作。

   - name: Getting the definition of awesome
      uri:
        url: https://api.chucknorris.io/jokes/random
        method: GET
      register: results

    - debug:
        var: results

运行它以查看 debug 生成的输出

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
    "results": {
        "alt_svc": "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400, h3-28=\":443\"; ma=86400, h3-27=\":443\"; ma=86400",
        "cf_cache_status": "DYNAMIC",
        "cf_ray": "694f7d791aeb19e7-EWR",
        "changed": false,
        "connection": "close",
        "content_type": "application/json;charset=UTF-8",
        "cookies": {},
        "cookies_string": "",
        "date": "Sun, 26 Sep 2021 21:12:23 GMT",
        "elapsed": 0,
        "expect_ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
        "failed": false,
        "json": {
            "categories": [],
            "created_at": "2020-01-05 13:42:26.991637",
            "icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
            "id": "IjqNNWKvSDeVKaI82PaT1g",
            "updated_at": "2020-01-05 13:42:26.991637",
            "url": "https://api.chucknorris.io/jokes/IjqNNWKvSDeVKaI82PaT1g",
            "value": "One person stated that Chuck Norris has forgotten more about killing than anyone will ever know. That is not true -- Chuck Norris never forgets. Ever."
        },
        "msg": "OK (unknown bytes)",
        "nel": "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}",
        "redirected": false,
        "report_to": "{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=HVPJYMVr%2B3wB1HSlgxv6GThBMjkBJgfdu0DPw%2BunjQzQ9YfXZqifggIJ%2FxOIKgOu6JP1SrPsx1jCCp3GQ9hZAp7NO0pmlTZ0y3ufbASGwLmCOV1zyaecUkSwQD%2Fv3RYYgZTkaSQ%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}",
        "server": "cloudflare",
        "status": 200,
        "transfer_encoding": "chunked",
        "url": "https://api.chucknorris.io/jokes/random",
        "via": "1.1 vegur"
    }
}

现在您可以看到所有输出,创建一个自定义消息,列出 API 返回的值。 这是完整的 playbook

---
- name: Using a REST API
  become: false
  hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: “Let’s call an API”

    - name: Everyone loves a good Chuck Norris joke
      uri:
        url: https://api.chucknorris.io/jokes/random
        method: GET
      register: results

    - debug:
        var: results.json.value

现在是完整的输出

PLAY [Using a REST API] *********************************************************************************************

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
    "msg": "“Let’s call an API”"
}

TASK [Everyone loves a good Chuck Norris joke] **********************************************************************
ok: [localhost]

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
    "results.json.value": "Chuck Norris is the only computer system that beats a Mac or a PC. Too bad all it does is round house kicks the user."
}

PLAY RECAP **********************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

下一步

事情可能会比我这里展示的复杂得多。 要获得更多详细信息,请前往 Ansible 的 文档

接下来阅读什么
标签
Avatar
我涉足开发、安全和运维的所有事情。 我敢打赌,有一个流行语适合我所做的事情。

评论已关闭。

Creative Commons License本作品采用 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.