选题[tech]: 20210930 Using Ansible with REST APIs

sources/tech/20210930 Using Ansible with REST APIs.md
This commit is contained in:
DarkSun 2021-10-01 05:03:48 +08:00
parent 15291e2f28
commit 3ee76f124b

View File

@ -0,0 +1,212 @@
[#]: subject: "Using Ansible with REST APIs"
[#]: via: "https://opensource.com/article/21/9/ansible-rest-apis"
[#]: author: "Vince Power https://opensource.com/users/vincepower"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Using Ansible with REST APIs
======
You may have queried APIs with a web browser or curl, but one of the
overlooked capabilities of Ansible is how well it can leverage APIs as
part of any playbook.
![Looking at a map][1]
Ansible is a top open source project which, on the surface, looks to provide a simple way to standardize your existing automation and allow it to run in parallel across multiple hosts, and it does this very successfully. Yet, in reality, Ansible has the capabilities to extend what your existing automation does to incorporate other systems and really simplify tasks across all aspects of your daily routine.
This capability starts with the [collections][2] and [roles][3] that are included with Ansible and all the third-party utilities distributed through [Ansible Galaxy][4]. You may have queried APIs with a web browser or [curl][5], but one of the overlooked capabilities of Ansible is how well it can leverage APIs as part of any playbook. This is extremely useful because the number of REST APIs being built and deployed both internally and across the global internet is increasing exponentially. There's even a [public-apis GitHub repo][6] listing hundreds of free APIs across over a dozen categories just for a sense of scale.
### A basic API playbook
Well, it really comes down to a few key core capabilities within Ansible, which are exposed nicely with one specific built-in task, _uri_. In this post, I'll go through a fairly simple example of how to call a REST API and use the data from that call to decide what to do next. This works with Ansible 2.9 and higher. In later versions (specifically v4), the modules we use need to be prepended with _ansible.builtin_ like _ansible.builtin.set_fact_ instead of just _set_fact_.
To get started, you need a basic playbook to build on. In this case, you're only using local calls, so you don't need to be a superuser.
First, create this YAML file to establish a working baseline:
```
\---
\- name: Using a REST API
  become: false
  hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: “Lets call an API”
```
Here's the output after running it:
```
% ansible-playbook using-a-rest-api.yml
PLAY [Using a REST API] *********************************************************************************************
TASK [debug] ********************************************************************************************************
ok: [localhost] => {
    "msg": "“Lets call an API”"
}
PLAY RECAP **********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
```
### Calling an API
To call an actual API, you can use the _uri_ module. Here are two examples. The first is just a GET and the second is a POST with parameters to show the different available options.
```
\---
\- 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
```
I use the first API for the rest of this article to show how the returned data can be used. The question is, how do you collect the data being returned, and what does it look like?
To collect the output from any task running in Ansible, you use the _register_ attribute, and then you can use the _debug_ task to display the raw data. In the case of APIs called using _uri_, all the output is put under the .json. Subsection of the result. The _uri_ commands and other its output are also at that top level. These can be useful to make sure the API call works by looking at other data fields like status.
These are the two tasks you must add to the original playbook to add the API call to the mix to later do something with.
```
  - name: Getting the definition of awesome
      uri:
        url: <https://api.chucknorris.io/jokes/random>
        method: GET
      register: results
    - debug:
        var: results
```
Run it to see the output generated by debug:
```
TASK [debug] ********************************************************************************************************
ok: [localhost] =&gt; {
    "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"
    }
}
```
Now that you can see all the output make a custom message listing the value returned by the API. Here is the completed playbook:
```
\---
\- name: Using a REST API
  become: false
  hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: “Lets 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
```
And now the complete output:
```
PLAY [Using a REST API] *********************************************************************************************
TASK [debug] ********************************************************************************************************
ok: [localhost] =&gt; {
    "msg": "“Lets call an API”"
}
TASK [Everyone loves a good Chuck Norris joke] **********************************************************************
ok: [localhost]
TASK [debug] ********************************************************************************************************
ok: [localhost] =&gt; {
    "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  
```
### Next steps
Things can get much more complicated than I've shown here. To get more details, head over to Ansible's [documentation][7].
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/9/ansible-rest-apis
作者:[Vince Power][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/vincepower
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/tips_map_guide_ebook_help_troubleshooting_lightbulb_520.png?itok=L0BQHgjr (Looking at a map)
[2]: https://docs.ansible.com/ansible/latest/user_guide/collections_using.html
[3]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
[4]: https://galaxy.ansible.com/
[5]: https://www.redhat.com/sysadmin/use-curl-api
[6]: https://github.com/public-apis/public-apis
[7]: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/uri_module.html