Ansible PlaybookでのJMESPath利用サンプル

## はじめに
AnsibleのPlaybookでの各タスクにおける実行結果は、registerパラメータ値で指定した変数に情報が格納されます。格納された情報はJSON形式で見ることができますが、その中から必要な情報だけを抽出したいと思ったときに活躍するのが、[JMESPath](https://jmespath.org/)です。ここでは、簡単なJMESPathを利用した情報抽出方法のサンプルをご紹介します。

## 検証環境
* Redhat Enterprise Linux 8.6
* Ansible core 2.12.2
* python 3.8.12

## 情報抽出が簡単なケース
JSONの中身が下記のような出力になっているケースであれば、抽出方法は簡単です。(以下は出力サンプル)
```
{
 "aaaa" : {
    :
   (略)
    :
    "bbbb" : {
       "name" : "ccccccc"
        }
    ：
    (略)  
    }
}
```
上記で"name"の情報を抽出したい場合には、Ansible Playbookで下記のように記載します。(以下はサンプル)
```yaml:case1.yaml

- hosts: localhost
  gather_facts: false
  
  tasks:

    - name: Running testmodule
      testmodule:
      register: result

    - name: Display policy name for S3AccessRole
      debug:
        msg: "{{result.aaaa.bbbb.name}}"
```
result変数に格納された結果を元に単純な階層指定(<font color="blue">result.aaaa.bbbb.name</font>)でnameの値を抽出することが可能です。

## 情報抽出に工夫がいるケース
JSONの中身に配列記法"["が使われているようなケースが該当します。(以下はAWSの[iam_role_info](https://docs.ansible.com/ansible/2.9_ja/modules/iam_role_info_module.html#iam-role-info-module)モジュールを実行した場合の出力サンプル)
```
{
 "iam_roles" : [
    :
   (略)
    :
    "managed_policies" : [
       {
          "policy_arn": "arn:aws:iam::aaaaaaaaaaaa:policy/S3AccessPolicy",   
          "policy_name" : "S3AcccessPolicy"
        }
      ]
    ：
    (略)  
    }
}
```
上記の出力から、"policy_name"の情報だけを抽出したい場合、JMESPathの配列記法に習い、AnsibleのPlaybookで下記のように記載します。
```yaml:case2.yaml
- hosts: localhost
  gather_facts: false
  
  tasks:

    - name: Get IAM Role Information
      iam_role_info:
        name: S3AccessRole
      register: result

    - name: Display all Information For S3AccessRole
      debug:
        msg: "{{result}}"

    - name: Display policy name for S3AccessRole
      debug:
        msg: "{{result.iam_roles[0].managed_policies[0].policy_name}}"
```
配列記法"["が使われている場合には、単純に(<font color="red">result.iam_roles.managed_policies.policy_name</font>)と記載するとPlaybook実行時にエラーになります。そのため、ここでは(<font color="blue">result.iam_roles[0].managed_policies[0].policy_name</font>)のように記載すれば、問題なく"policy name"の値のみを抽出してくることが可能になります。

* 実行結果 (一部の情報はマスキングしています。)
```
[testuser@localhost aws]$ ansible-playbook case2.yaml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost
does not match 'all'

PLAY [localhost] **************************************************************************************

TASK [Get IAM Role Information] ***********************************************************************
ok: [localhost]

TASK [Display all Information For S3AccessRole] *******************************************************
ok: [localhost] => {
    "msg": {
        "changed": false,
        "failed": false,
        "iam_roles": [
            {
                "arn": "arn:aws:iam::aaaaaaaaaaaaaa:role/S3AccessRole",
                "assume_role_policy_document": {
                    "statement": [
                        {
                            "action": "sts:AssumeRole",
                            "condition": {},
                            "effect": "Allow",
                            "principal": {
                                "aws": "arn:aws:iam::bbbbbbbbbb:root"
                            }
                        }
                    ],
                    "version": "2012-10-17"
                },
                "create_date": "2022-08-11T01:28:04+00:00",
                "description": "",
                "inline_policies": [],
                "instance_profiles": [],
                "managed_policies": [
                    {
                        "policy_arn": "arn:aws:iam::aaaaaaaaaaaa:policy/S3AccessPolicy",
                        "policy_name": "S3AccessPolicy"
                    }
                ],
                "max_session_duration": 3600,
                "path": "/",
                "role_id": "cccccccccccccccccccc",
                "role_last_used": {
                    "last_used_date": "2022-08-11T01:55:43+00:00",
                    "region": "us-east-1"
                },
                "role_name": "S3AccessRole",
                "tags": {
                    "Name": "S3Access"
                }
            }
        ]
    }
}

TASK [Display policy name for S3AccessRole] ***********************************************************
ok: [localhost] => {
    "msg": "S3AccessPolicy"
}

PLAY RECAP ********************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```
# おわりに
本記事では、AnsibleのPlaybookの実行結果を変数に格納し、そこから必要な情報を抽出したい場合に、単純抽出できるケースと工夫がいるケースのサンプルをご紹介しました。全てのモジュールの実行結果の出力の仕方が統一されていれば、このように迷う必要もないと思うのですが、こればかりは文句を言ってもしょうがないので、JMESPath(JSONのクエリ言語)もより活用できるようになればと思います。