【Ansible】uriモジュールの癖がすごい件について

f:id:hira98:20190717221159p:plain

【追記 2019/07/18】 return_content: yesの指定を追加すれば、成功時もcontent(ブラウザに表示されるデータ)を返してくれました。

【結論】

  • AnsibleではHTTPリクエストを投げるためにuriモジュールが提供されている。
  • ブラウザでHTTPリクエストを投げると、HTMLファイルを返してくれる。
  • だから、uriモジュールも同じノリでしょ😤とタカをくくると痛い目を見る😭
  • uriモジュールは想定したHTTPステータスコード以外が返ってきた時のみ、content(ブラウザに表示されるデータ)を失敗結果として返す。

【目次】

はじめに

REST APIが提供されている機器をAnsibleから制御するために、uriモジュールを使った際にハマった内容についてまとめました。

開発環境の構成

簡単な構成図は以下になります。

操作用PCから検証環境の踏み台環境にリモート接続して開発しています。

図だと、操作用PCと踏み台環境は直接繋がっていますが、本当は色々な機器を介しているはずです。ですが、把握していないのと、今回の記事の内容では触れないので省略しています。

踏み台環境にリモートで接続すると、同じLAN内にあるAnsibleサーバーや制御対象機器へはブラウザから操作することができます。

f:id:hira98:20190717221246p:plain

踏み台環境から制御対象機器へ要求

踏み台環境のブラウザから制御対象機器を操作するAPI(仮にyahoo.co.jpとします。)を実行すると、結果がブラウザに表示されます。

Ansibleサーバーから制御対象機器へ要求してみると

踏み台環境からAnsibleサーバーへSSHで接続して、CURLコマンドを実行すると意図した結果が返ってきます。

Ansibleサーバーからuriモジュールを使って制御対象機器へ要求してみる

ここからが本題です。次のようなプレイブックを書いて実行してみました。

プレイブック(.yml)

---
- hosts: localhost  # 自分自身に接続する
  tasks:
  - uri:
      url: http://yahoo.co.jp
      method: GET
      status_code: 200 
    register: _result  

  - debug: msg="{{_result}}

実行結果(debugの抜粋)

実行結果を見ると色々出てますが、yahooのトップページを要求したはずなのにhtml文が一切出力されていません。

ok: [localhost] => {
    "msg": {
        "age": "0", 
        "cache_control": "private, no-cache, no-store, must-revalidate", 
        "changed": false, 
        "connection": "close", 
        "content_type": "text/html; charset=UTF-8", 
        "cookies": {}, 
        "cookies_string": "", 
        "date": "Wed, 17 Jul 2019 12:38:31 GMT", 
        "elapsed": 0, 
        "expires": "-1", 
        "failed": false, 
        "msg": "OK (unknown bytes)", 
        "p3p": "policyref=\"http://privacy.yahoo.co.jp/w3c/p3p_jp.xml\", CP=\"CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV\"", 
        "pragma": "no-cache", 
        "redirected": true, 
        "server": "ATS", 
        "status": 200, 
        "transfer_encoding": "chunked", 
        "url": "https://www.yahoo.co.jp/", 
        "vary": "Accept-Encoding", 
        "via": "http/1.1 edge1640.img.bbt.yahoo.co.jp (ApacheTrafficServer [c sSf ])", 
        "x_content_type_options": "nosniff", 
        "x_frame_options": "SAMEORIGIN", 
        "x_xss_protection": "1; mode=block"
    }
}

uriモジュールの実行結果がHTML文を返さない理由

結論から言うと、uriモジュールの引数として指定するstatus_code(デフォルトは200)で指定したHTTPステータスコードと、HTTPリクエスト結果のHTTPステータスコードが一致する場合は成功と判断して余計な結果は返さない仕様となっているからです。

よって、以下のようにstatus_codeを200以外に変えると、実行結果としてHTML文が出力されるようになります。

---
- hosts: localhost  # 自分自身に接続する
  tasks:
  - uri:
      url: http://yahoo.co.jp
      method: GET
      status_code: 100 # 200→100に変更 
    register: _result  
  - debug: msg="{{_result}}"

実行結果

content=以降がHTML文になります。ただし、このままだとエスケープシーケンス文字が大量に含まれてて見ずらいので置換が必要です。

fatal: [localhost]: FAILED! => {"age": "0", "cache_control": "private, no-cache, no-store, must-revalidate", "changed": false, "connection": "close", "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n<meta http-equiv=\"content-style-type\" content=\"text/css\">\n<meta http-equiv=\"content-script-type\" content=\"text/javascript\">\n<meta name=\"description\" content=\"日本最大級のポータルサイト。検索、オークション、ニュース、メール、コミュニティ、ショッピン
〜〜省略〜〜

uriモジュール開発者の考え(勝手な想像)

AnsibleでHTTPリクエスト投げるケースでは、ブラウザに表示される情報なんて出す必要ないでしょ😎

でもデバッグ時は必要だろうから、HTTPステータスコードが想定した結果と違う時だけ結果として返して処理失敗にすればいいでしょ😎

参考情報

uri – Interacts with webservices — Ansible Documentation

さいごに

キーボード操作やマウス操作が直ぐに画面に反映されるのが嬉しくてたまらんのですが。。。