等待 API 回應完成

情境是這樣的,Playbook 在送出 HTTP 請求後,需要送出一個 HTTP 請求去持續詢問是否完成,如果還沒完成,就等待一段時間後,再去詢問,那這個情境下可以怎麼做呢?

若是寫程式,一般會用一個迴圈持續的去發送 HTTP 請求,取得回傳值以後,看是否完成,若還沒有,就等待一下,重複前面的步驟;若是已經完成就跳離迴圈。

Ansible playbook 裡的迴圈是變形過的,不太適合這樣做,好在 uri 模組本身已經有提供這種機制。

下面直接看範例

---
- name: Playbook for Web automation
  hosts: localhost

  tasks:
  - name: Check if API is available and returning status 200
    uri:
      url: https://<api-server>/api/status
    register: result
    until: "result.status == 200"
    retries: 5
    delay: 10

這會對 https:///api/status 這個端點發送 HTTP 請求,然後看回應的狀態碼是否為 200 ,若不是,就重試 5 次,每次間隔 10 秒。

上面範例是使用 GET,那如果是用 POST,又該怎麼寫?

- name: Playbook for Web automation
  hosts: localhost

  tasks:
  - name: Wait for API endpoint to return 201 created
    uri:
      url: "https://<api-server>/api/users"
      method: POST
      body: |-
        {
          "name": "John",
          "Location": "Taiwan"
        }        
      return_content: yes
      status_code: 201
    register: uri_result
    until: "uri_result.status == 201"
    retries: 5
    delay: 10
  - debug:
      var: uri_result.content

這邊就是對 https:///api/users 發送 HTTP 請求,然後看回應的狀態是否為 201,若不是,就重試 5 次,每次間隔 10 秒。

until 裡也可以使用回傳回來的 JSON 內容來做檢查,例如

- name: Playbook for Web automation
  hosts: localhost

  tasks:
  - name: Wait for API endpoint to return token
    uri:
      url: "https://<api-server>/api/login"
      method: POST
      body_format: json
      body: |-
        {
          "name": "John",
          "password": "password"
        }        
      return_content: yes
    register: uri_result
    until: "'token' in uri_result.content"
    retries: 5
    delay: 10
  - debug:
      var: uri_result.content

這邊就是檢查回傳內容是否有 ’token'

透過以上的範例,相信你已經知道

  1. uri 模組可以用來存取 Web API 或是某個網址。
  2. 透過 retry until 的組合,可以用來驗證結果,並持續重試直到滿足條件。

參考資料