AnsibleでREST APIリクエストする方法
Ansibleを使う時、当然Playbookを記述するわけですが、以下の観点からなるべくshellモジュールやcommandモジュールなどのコマンドを記述するモジュールを使わず、その対象機器に特化したモジュールを使えないか検討する必要があります。
- Playbookとしての冪等性を担保するため
- 宣言型の記述により、このPlaybookを流したらどういう状態になるか読んでもわかるようにするため
ただ、どうしても最適なモジュールがない場合は、Command系のモジュールの使用を検討することになりますが、対象機器がREST APIのインターフェースを持っている場合は、AnsibleからAPIをリクエストして機器を操作する方法も考えられます。
REST APIリクエストをするモジュール
uriというモジュールを利用する。
例えばGETする場合はこんなTask記述になる。
tasks:
- name: Get event list
uri:
url: "https://xxxxx/xxxxxx/xxxx"
headers:
Accept: "xxxxxxx"
Authorization: "xxxxxxxx"
status_code: 200
method: GET
return_content: yes
register: result_get
指定したURLに対してGETリクエストして、結果をresult_get
へ保存する。REST APIは、Webサービスによって認証の仕組み(Tokenの送信)がほとんどの場合必要なので、ヘッダとして付与する。
REST APIリクエストする例
ここでは、超私的なニーズの元、手頃なサービスとしてTimeTreeのAPIを例として取り上げる。
実行環境
- Ansible 2.9.4
手順
-
App Consoleへのアクセスする
TimeTreeの開発者向けApp Consoleアクセスする -
発行されたTokenを保存しておく。
-
自分のカレンダーIDを保存しておく。
自分のカレンダーへアクセスした時のURLの最後の要素がカレンダーID。
https://timetreeapp.com/calendars/<カレンダーID>
ここまでで、TimeTreeへAPIでアクセスするために必要な情報として以下が揃った。- アクセストークン
- カレンダーID
-
AnsibleでAPIリクエスト
このPlaybookは、指定したカレンダーに対して以下を行う。- 直近のデータを取得(デバッグ的に)
- CSVからカレンダー登録するデータを読み込み
- APIを使って一括登録
- name: create events
hosts: localhost
gather_facts: no
connection: local
vars:
access_token: <Access Token>
calender_id: <CalenderID>
tasks:
- name: Get event list
uri:
url: "https://timetreeapis.com/calendars/{{ calender_id }}/upcoming_events?timezone=Asia/Tokyo&days=3&include=creator,label,attendees"
headers:
Accept: "application/vnd.timetree.v1+json"
Authorization: "Bearer {{ access_token }}"
status_code: 200
method: GET
return_content: yes
register: result_get_events_list
- name: debug
debug:
var: result_get_events_list
- name: Read users from CSV file and return a list
read_csv:
path: data.csv
register: data_schedules
delegate_to: localhost
- name: create event
uri:
url: "https://timetreeapis.com/calendars/{{ calender_id }}/events"
headers:
Accept: "application/vnd.timetree.v1+json"
Authorization: "Bearer {{ access_token }}"
Content-Type: "application/json"
body_format: json
body: '{"data":{"attributes":{"category":"schedule","title":"xx予定","all_day":false,"start_at":"{{ item.date }}T{{ item.startAt }}.000+09:00","start_timezone":"Asia/Tokyo","end_at":"{{ item.date }}T{{ item.endAt }}.000+09:00","end_timezone":"Asia/Tokyo","description":"{{item.description}}"},"relationships":{"label":{"data":{"id":"<CalenderID>,9","type":"label"}}}}}'
status_code: 201
method: POST
return_content: yes
register: result_create_event
with_items: "{{ data_schedules.list }}"
- name: debug
debug:
var: result_create_event
NO,date,startAt,endAt,description
1,YYYY-MM-DD,hh:mm:ss,hh:mm:ss,zzzzzzzzzzzzzzzz
2,YYYY-MM-DD,hh:mm:ss,hh:mm:ss,zzzzzzzzzzzzzzzz
:
Ansibleで実行
#ansible-playbook createEvents.yml
変数やURL、POSTするデータを全て一つのyamlに記述したのでキレイではないが、手っ取り早く一括API実行ができた。また、データ(CSV)を変えることで同じ手順をミスなく繰り返すことができるようになった。
エンタープライズでの運用では、運用対象がREST APIを持っている(Ansibleのモジュールはない)場合に、このようなデータだけが変わる定型運用を比較的簡単に自動化できる。
超私的なニーズ:
在宅勤務が続き、小学生娘が何時に家に帰ってくるかを把握したいけど学校から配布されるプリントを見るのが面倒だったので。もちろん会社のAnsibleの私的利用は厳禁です。