7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ニフティグループAdvent Calendar 2019

Day 3

AWXの通知をカスタマイズする

Last updated at Posted at 2019-12-02

この記事はニフティグループ Advent Calendar 2019の3日目の記事です。
昨日は @johnFkennedy さんで「teachablemachineを使って、なんかやってみた。」でした。コードなしで分類タスクを解けるのは魅力的ですね。

はじめに

この記事ではAWX上で実行した結果をカスタマイズしてslackに通知することをゴールとしています。

多人数でAnsibleを使う場合にはGUI上でタスクの実行、結果の確認ができるAWXが便利です。
AWXを管理する側としては誰が、いつ、どんなタスクを実行して、結果はどうだったのかを通知してもらいたいですよね。
そこで、実行結果を投げる設定をAWXのnotification_templateで行い、slack上でいい感じの通知をしてもらいます。

※slackへの通知はwebhook経由で行います。通知設定はこちらの記事などを参考に各自行ってください。AWXとの連携にはこちらの記事が参考になると思います

以下の作業はすべて通知の管理者権限を持っているものとします。

環境

 _______________ 
<  AWX 8.0.0.0  >
 --------------- 
        \   ^__^
         \  (oo)\_______
            (__)      A )\/\
                ||----w |
                ||     ||

Ansible 2.8.6

カスタムメッセージの追加方法

  1. 通知メニューからカスタムメッセージを追加したい通知テンプレートを選択します。
  2. 下の方にあるCUSTOMIZE MESSAGES...ONにします。
    image.png

以上でカスタムメッセージの追加は完了です

しかし、このままだとテンプレートを実行してもジョブが成功しても失敗しても以下のような無機質なメッセージしか流れません。

Job #3 'Demo Job Template' running: https://towerhost/#/jobs/playbook/3

これを温かみのあるものへと変更していきます。

メッセージのカスタマイズ

カスタムメッセージで使用できる変数

通知にはいつ、誰が、どのプレイブックを実行したか、などの情報が必要です。これらの情報はジョブ実行時にAnsible変数に格納され、流れていきます。
格納される変数のリストはAnsible Tower Documentationに記載されています。1
この変数を参照することで、各種ジョブの状態を確認することができます。

カスタムメッセージで変数を参照する場合には基本、{{ job.<使いたい変数> }}の形で記述していきます。
例えば、テンプレートの起動者をメッセージに追加する場合には{{ job.summary_fields.created_by.username }}と記述します。

具体的にどんな値が格納されているのか知りたいときには、一度{{ job }}のみを記述して、通知を流してみるのが良いです。
sample job templateを実行すると以下のようなjsonが返ってきます。

(折りたたみ)`{{ job }}`で流れてくる内容
{
    "id": 17, 
    "type": "job", 
    "url": "/api/v2/jobs/17/", 
    "created": datetime.datetime(2019, 11, 5, 4, 46, 2, 551213, tzinfo=), 
    "modified": datetime.datetime(2019, 11, 5, 4, 46, 16, 849290, tzinfo=), 
    "name": "Demo Job Template", 
    "description": "",
    "job_type": "run",
    "playbook": "hello_world.yml",
    "forks": 0, 
    "limit": "",
    "verbosity": 0, 
    "job_tags": "",
    "force_handlers": False, 
    "skip_tags": "",
    "start_at_task": "",
    "timeout": 0, 
    "use_fact_cache": False, 
    "launch_type": "manual",
    "status": "running",
    "failed": False, 
    "started": "2019-11-05T04:46:16.912606Z",
    "finished": None, 
    "elapsed": 0.148594, 
    "job_explanation": "",
    "execution_node": "awx",
    "controller_node": "",
    "allow_simultaneous": False, 
    "scm_revision": "",
    "diff_mode": False, 
    "job_slice_number": 0, 
    "job_slice_count": 1, 
    "summary_fields": {
        "inventory": {
            "id": 1, "name": "Demo Inventory",
            "description": "",
            "has_active_failures": False,
            "total_hosts": 1, 
            "hosts_with_active_failures": 0, 
            "total_groups": 0, 
            "groups_with_active_failures": 0, 
            "has_inventory_sources": False, 
            "total_inventory_sources": 0, 
            "inventory_sources_with_failures": 0, 
            "organization_id": 1, 
            "kind": ""
        }, 
        "project": {
            "id": 6, 
            "name": "Demo Project",
            "description": "",
            "status": "successful",
            "scm_type": "git"
        }, 
        "job_template": {
            "id": 7, 
            "name": "Demo Job Template",
            "description": ""
        }, 
        "unified_job_template": {
            "id": 7, 
            "name": "Demo Job Template",
            "description": "",
            "unified_job_type": "job"
        }, 
        "instance_group": {
            "name": "tower",
            "id": 1
        }, 
        "created_by": {
            "id": 1, 
            "username": "admin",
            "first_name": "",
            "last_name": ""
        }, 
        "labels": {
            "count": 0, 
            "results": []
        }
    }
}

jinja2 テンプレート

記述方法から気づく方もいらっしゃるかと思いますが、カスタムメッセージの変数はjinja2 テンプレートで記述します。
これにより、変数から得られる文字を自由に書き換えることが可能です。

例えば、{{ job.started }}はUTCだったり秒以下小数点が並んでいたりと見づらいです。
image.png

そこで、次のように書くことで、日本標準時に直すことができます。

"{{ job.started.split('T')[0] }} {{ job.started.split('T')[-1].split(':')[0] | int + 9 }}:{{ job.started.split('.')[0].split(':')[1:] | join(':') }}"

{{ job.finished }}はなぜかはじめにstringへの変換が必要でした。

"{% set f=job.finished ~ '' %}  {{ f.split('T')[0] }}  {{ f.split('T')[-1].split(':')[0] | int + 9 }}:{{ f.split('.')[0].split(':')[1:] | join(':') }}"

変更後はこうなりました。スッキリしましたね。
image.png

slack投稿のカスタマイズ

webhook経由でのslack通知の場合には、ペイロードをjsonで記述することができます。つまり、投稿するメッセージのフォーマットをある程度いじることができます。
slackへ投げるjsonの形式はslack Formatting messagesを参考にしてください。
slack Message Builderで記述した内容のチェックができて便利です。

最終的に完成した通知がこちらです。
image.png

以下通知に設定した内容になります。

START MESSAGE BODY
{
  "channel": "#test_notification", 
  "username": "AnsibleNotice",
  "text": "{{ job.summary_fields.created_by.username }} が {{ job.name }} を開始しました", 
  "icon_emoji": ":passport_control:"
}
SUCCESS MESSAGE BODY
{
  "channel": "#test_notification", 
  "username": "AnsibleNotice",
  "attachments": [
      {
          "fallback": "{{ job.name }} is {{ job.status }}",
          "color": "good",
          "author_name": "{{ job.summary_fields.created_by.username }}",
          "title": "{{ job.name }}",
          "title_link": "{{ url }}",
          "pretext": "{{ job.summary_fields.created_by.username }} が {{ job.name }} を {{ job.status }} で終了しました",
          "fields": [
              {
                "title": "started",
                "value": "{{ job.started.split('T')[0] }} {{ job.started.split('T')[-1].split(':')[0] | int + 9 }}:{{ job.started.split('.')[0].split(':')[1:] | join(':') }}",
                "short": "true"
              },
              {
                "title": "finished",
                "value": "{% set f=job.finished ~ '' %}  {{ f.split('T')[0] }}  {{ f.split('T')[-1].split(':')[0] | int + 9 }}:{{ f.split('.')[0].split(':')[1:] | join(':') }}",
                "short": "true"
              },
              {
                "title": "project",
                "value": "{{ job.summary_fields.project.name }}",
                "short": "true"
              },
              {
                "title": "inventory",
                "value": "{{ job.summary_fields.inventory.name }}",
                "short": "true"
              },
              {
                "title": "job_template",
                "value": "{{ job.summary_fields.job_template.name }}",
                "short": "true"
              },
              {
                "title": "instance_group",
                "value": "{{ job.summary_fields.instance_group.name }}",
                "short": "true"
              },
              {
                "title": "playbook",
                "value": "{{ job.playbook }}",
                "short": "true"
              }
          ],
          "footer": "AWX Notification"
      }
  ],
  "icon_emoji": ":passport_control:"
}
ERROR MESSAGE BODY
{
  "channel": "#test_notification", 
  "username": "AnsibleNotice",
  "attachments": [
      {
          "fallback": "{{ job.name }} is {{ job.status }}",
          "color": "danger",
          "author_name": "{{ job.summary_fields.created_by.username }}",
          "title": "{{ job.name }}",
          "title_link": "{{ url }}",
          "pretext": "{{ job.summary_fields.created_by.username }} が {{ job.name }} を {{ job.status }} で終了しました",
          "fields": [
              {
                "title": "started",
                "value": "{{ job.started.split('T')[0] }} {{ job.started.split('T')[-1].split(':')[0] | int + 9 }}:{{ job.started.split('.')[0].split(':')[1:] | join(':') }}",
                "short": "true"
              },
              {
                "title": "finished",
                "value": "{% set f=job.finished ~ '' %}  {{ f.split('T')[0] }}  {{ f.split('T')[-1].split(':')[0] | int + 9 }}:{{ f.split('.')[0].split(':')[1:] | join(':') }}",
                "short": "true"
              },
              {
                "title": "project",
                "value": "{{ job.summary_fields.project.name }}",
                "short": "true"
              },
              {
                "title": "inventory",
                "value": "{{ job.summary_fields.inventory.name }}",
                "short": "true"
              },
              {
                "title": "job_template",
                "value": "{{ job.summary_fields.job_template.name }}",
                "short": "true"
              },
              {
                "title": "instance_group",
                "value": "{{ job.summary_fields.instance_group.name }}",
                "short": "true"
              },
              {
                "title": "playbook",
                "value": "{{ job.playbook }}",
                "short": "true"
              }
          ],
          "footer": "AWX Notification"
      }
  ],
  "icon_emoji": ":passport_control:"
}

あとがき

AWXから送信される通知を無機質なものから、温かみのあるものへと変更しました。通知を見るたびに柔らかなbotらしさを感じることができます。
皆様もよいAWXライフを送ってください。

  1. 11/13のVersion 3.6.0 updateに伴って、Tower Documentationにvariablesについての記述が追加されました。

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?