Contents
GitLabのリポジトリに対してPushをトリガーにAnsible Towerのワークフローをキックして結果のステータスをGitLabのリポジトリへ反映する方法です。
イメージ
以下はイメージ図です。
ユーザーがリモートのリポジトリにpushをしたタイミングでWebhookサーバにWebhookを飛ばしてAnsible TowerのWFを実行し結果をGitLabに反映します。
環境
コンポーネント | バージョン | 備考 |
---|---|---|
CentOS | 7.7 | Webhookサーバ |
RHEL | 7.6 | Ansible Towerサーバ |
GitLab | 12.2.5 | |
Ansible Tower | 3.5.1 | |
Webhook | 2.6.10 | Go製 |
Webhook
Webhookインストール
インストール方法は以下を参照してください。
Webhook設定
Webhookは以下のように設定します。
1 2 3 4 |
(venv) [root@Webhook01 ~]# cd /opt/ (venv) [root@Webhook01 opt]# mkdir ansible-tower-wf (venv) [root@Webhook01 ansible-tower-wf]# vi hooks.json |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
[ { "id": "ansible-tower-wf", "execute-command": "/opt/ansible-tower-wf/run-ansible-tower-wf.sh", "command-working-directory": "/opt", "pass-arguments-to-command": [ { "source": "payload", "name": "project_id" }, { "source": "payload", "name": "checkout_sha" }, { "source": "payload", "name": "project.web_url" } ], "trigger-rule": { "and": [ "match": { "type": "value", "value": "GQaATMBq8APLvGuzp4bca87eBHcT05", "parameter": { "source": "header", "name": "X-Gitlab-Token" } } ] } } ] |
trigger-rule
の X-Gitlab-Token
に設定してある value
は以下のコマンドでランダムに生成しています。
1 2 3 |
(venv) [root@Webhook01 ansible-tower-wf]# cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 30 ; echo GQaATMBq8APLvGuzp4bca87eBHcT05 |
これは、GitLabからWebhookを受け取ったときに同じ値のX-Gitlab-Tokenヘッダーがあれば実行すると言うルールです。
Webhookで実行されるスクリプトの引数は以下の通りです。
引数番号 | name | 説明 |
---|---|---|
1 | project_id | プロジェクトのID |
2 | checkout_sha | リポジトリへコミットしたハッシュ値 |
3 | project.web_url | リポジトリへのWeb URL |
スクリプト
Webhookの条件が満たされた場合に実行されるスクリプトは以下のように作成しています。
1 2 |
(venv) [root@Webhook01 ansible-tower-wf]# vi run-ansible-tower-wf.sh |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/bin/bash # GitLab Variables project_id=$1 commit_hash=$2 gitlab_server=`echo $3 | cut -d '/' -f 3` gitlab_token='H4_N99yzHE8FepTyrpQu' # Ansible Tower Variables ansible_tower='192.168.0.64' ansible_user='admin' ansible_password='redhat' ansible_wf='ansible-tower-gitlab-wf' source /opt/ansible-tower-wf/venv/bin/activate && tower-cli workflow_job launch -W $ansible_wf -e "{\"project_id\": $project_id, \"commit_hash\": $commit_hash, \"gitlab_server\": $gitlab_server, \"GitLab_TOKEN\": $gitlab_token }" \ -h $ansible_tower -u $ansible_user -p $ansible_password --insecure |
スクリプトで取り扱う変数は以下の通りです。
変数名 | 説明 | 備考 |
---|---|---|
project_id | GitLabのプロジェクトのID | 1番目の引数 |
commit_hash | GitLabのコミットハッシュ値 | 2番目の引数 |
gitlab_server | GitLabサーバのホスト | 3盤面の引数 |
gitlab_token | GitLabで生成したToken | |
ansible_tower | Ansible Towerのホスト | |
ansible_user | Ansible Towerのユーザー | |
ansible_password | Ansible Towreのパスワード | |
ansible_wf | 実行するAnsible Towerのワークフロー名 |
gitlab_token
は次のGitLabのTokenの発行で発行した値を指定します。
GitLab
Tokenの発行
GitLabのリポジトリに外部からアクセスするようのトークンを生成します。
ユーザー
の Settings
をクリックします。
Access Token
をクリックして Name
を入力し api
にチェックを入れ Create personal access token
をクリックします。
生成されたトークンを控えておきます。
Webhook設定
リポジトリの Settings
の Integrations
をクリックします。
URL
にwebhookのURLを入力し SecretToken
にコマンドでランダムに生成した値を入れ Add webhook
をクリックします。
Ansible Tower
Playbook
Playbookは以下の3つを作成しました。
Playbook | 説明 |
---|---|
main.yml | pingモジュールを実行する |
gitlab-build-status-running.yml | GitLabリポジトリステータスを running にする |
gitlab-build-status-success.yml | GitLabリポジトリステータスを success にする |
gitlab-build-status-failed.yml | GitLabリポジトリステータスを failed にする |
GitLabのリポジトリステータスはWeb API経由で変更しています。
APIドキュメントは以下を参照してください。
main.yml
1 2 3 4 5 6 7 |
--- - name: Ping hosts: all gather_facts: no tasks: - ping: |
gitlab-build-status-running.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
--- - name: GitLab Status Updte hosts: localhost gather_facts: no tasks: - name: GitLab build status is running uri: url: "http://{{ gitlab_server }}/api/v4/projects/{{ project_id }}/statuses/{{ commit_hash }}?state=running" method: POST headers: PRIVATE-TOKEN: "{{ GitLab_TOKEN }}" status_code: 201 |
gitlab-build-status-success.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
--- - name: GitLab Status Updte hosts: localhost gather_facts: no tasks: - name: GitLab build status is running uri: url: "http://{{ gitlab_server }}/api/v4/projects/{{ project_id }}/statuses/{{ commit_hash }}?state=success" method: POST headers: PRIVATE-TOKEN: "{{ GitLab_TOKEN }}" status_code: 201 |
gitlab-build-status-failed.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
--- - name: GitLab Status Updte hosts: localhost gather_facts: no tasks: - name: GitLab build status is running uri: url: "http://{{ gitlab_server }}/api/v4/projects/{{ project_id }}/statuses/{{ commit_hash }}?state=failed" method: POST headers: PRIVATE-TOKEN: "{{ GitLab_TOKEN }}" status_code: 201 |
Project設定
Template設定
ansible-tower-gitlab-wf-main
main.ymlを実行するTemplateです。
GitLab Build Status Running
gitlab-build-status-running.ymlを実行するTemplateです。
GitLab Build Status Success
gitlab-build-status-success.ymlを実行するTemplateです。
GitLab Build Status Failed
gitlab-build-status-failed.ymlを実行するTemplateです。
Workflow Template設定
ansible-tower-gitlab-wf
今回作成したPlaybookを組み合わせて実行させるWorkflow Templateです。
SURVEYは以下のようにしています。
GitLab_TOKEN
をAnsible Towerの履歴から見れないようにマスクしています。
Workflowは以下のように作成しています。
番号 | 説明 |
---|---|
(1) | GitLabのリポジトリステータスをrunningに変更 |
(2) | テスト処理、ここでは例としてpingするだけのPlaybookを実行 |
(3) | 問題なければGitLabのステータスをsuccessに変更 |
(4) | 失敗した場合はGitLabのステータスをfailedに変更 |
デモ
実際に動かしてみたデモです。
Demo to run CI with Ansible Tower workflow by combining Ansible Tower and GitLab from sky_joker on Vimeo.
最後に
Ansible TowerとGitLabとWebhookを組み合わせる事でAnsible TowerのワークフローでCIちっくなことが出来そうですね。
ただ、今まで通りのCIツール(TravisとかShippabletとかJenkinsなど)ではないので、CIファイルにコマンド書きではなくPlaybookを作る必要があります。
なので、向き不向きがかなり分かれそうな感じがします。
どういったユースケースの場合だと便利かは今後も検証して確認してみようと思います 🙂
それでは、みんなでハッピーオートメーション!