ローカルAnsible GalaxyでプライベートなCollection管理

※2021/01/31追記
今からやるなら[Galaxy NG版](https://qiita.com/ussvgr/items/d1253a0fd65667632fdc) の方がおすすめです。

# はじめに
Ansibleでロールを共有する仕組みとして[Ansible Galaxy](https://galaxy.ansible.com/)がありますが、社内でしか使えないプライベートなロールなど、世界中に晒せないような物を載せるのは躊躇してしまいます。
幸いにしてAnsible Galaxyは[OSSとして公開されている](https://github.com/ansible/galaxy)ので、ローカルで管理することが可能です。
[Contributor Guide](https://github.com/ansible/galaxy/blob/devel/CONTRIBUTING.rst)に起動方法が記載されているので、試してみました。
（ちょっと触ってみただけなので、間違いなどあってもご容赦を…）

# 前提
実はロールについては（Ansible Galaxyでは）プライベートな管理ができません。Githubでの公開が必須なようです。（Privateなリポジトリではダメでした）
※3/25追記 Galaxyを利用しない前提であれば、Gitを直接参照することでRoleの管理自体は可能です。↑で書いているのは、あくまで「ローカルで立てたAnsible Galaxyでは」という前提です。

ですが、表題にある[コレクション](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html)であればtar ballをアップロードする形で管理できるので、プライベートな管理が可能です。
認証のためにGithubのアカウントは必須となるので注意。
環境面として、Docker + Docker Composeが動く環境が必要です。

# 環境構築
##コンテナ起動
まずはリポジトリをクローンし、コンテナイメージをビルドします。

```bash
$ git clone https://github.com/ansible/galaxy
$ cd galaxy
$ make dev/build
```
「galaxy-dev」というイメージが出来上がっていればOK。

```bash
$ docker images
REPOSITORY                                                  TAG                 IMAGE ID            CREATED             SIZE
galaxy-dev                                                  latest              e73986ff5fbf        2 hours ago         1.02GB
...
```
以下のコマンドで起動します。

```bash
$ make dev/up_detached
```
ビルドしたイメージ以外に、PostgreSQL, rabbitMQ, influxDB, redisのコンテナが起動します。

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                NAMES
d8a0135542d8        galaxy-dev:latest   "/entrypoint start t…"   2 hours ago         Up 2 hours          0.0.0.0:8000->8000/tcp               galaxy_galaxy_1
5c7cdba1e404        postgres:9.5        "docker-entrypoint.s…"   3 hours ago         Up 3 hours          0.0.0.0:2345->5432/tcp               galaxy_postgres_1
67210023161e        rabbitmq:latest     "docker-entrypoint.s…"   3 hours ago         Up 3 hours          4369/tcp, 5671-5672/tcp, 25672/tcp   galaxy_rabbitmq_1
9028fbe7fec6        influxdb:latest     "/entrypoint.sh infl…"   3 hours ago         Up 3 hours          0.0.0.0:8086->8086/tcp               galaxy_influxdb_1
2906df012857        redis:latest        "docker-entrypoint.s…"   3 hours ago         Up 3 hours          6379/tcp                             galaxy_redis_1
```

しばらく待ってからhttp://\<DockerホストのIP\>:8000/ にアクセスすると、
![スクリーンショット 2020-03-22 0.15.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/5d4c7ff5-3579-94ca-df8d-2d65495a3756.png)
こんな画面になっているはずです。

##初期設定
このままだとログインできないため、Githubアカウントへのアプリ登録が必要となります。
まずは管理用ユーザーを作成します。この時、Githubアカウントで利用しているEmailアドレスを使用してはいけません。

```bash
$ make dev/createsuperuser
Create Superuser

Username: <管理ユーザー名>
Email address: <Githubに登録している以外のメールアドレス>
Password: <パスワード>
Password (again): <パスワード再入力>
Superuser created successfully.
```
Githubにログインし、右上の自分のアイコンをクリック→Settingsを選択。
左メニューからDeveloper settingsを選び、OAuth Appsの「Register a new application」をクリックします。
![スクリーンショット 2020-03-22 0.25.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/152f8b81-e3ad-496e-3d8f-c24cdc8809e8.png)

Application name: 任意の名前
Homepage URL: http://\<DockerマシンのIP\>:8000
Authorization callback URL: http://\<DockerホストのIP\>:8000/accounts/github/login/callback/
を入力して、「Register application」ボタンをクリックし、
![スクリーンショット 2020-03-22 0.26.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/b2a71b22-3ef4-a5ad-e9ed-4bd59677c4de.png)

表示されるClient IDとClient Secretの値を控えておきます。
![スクリーンショット 2020-03-22 0.32.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/a6a161fb-8a0d-3190-8938-3d98ee7617c8.png)

http://\<DockerホストのIP\>:8000/adminを開くと、Djangoのログイン画面になるので、先ほど作成した管理用ユーザーでログインします。

SITES->Sitesの項目へ飛び、example.comとなっている行のDomain nameとDisplay nameをDockerマシンのIPに書き換えます。
![スクリーンショット 2020-03-22 0.40.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/b9f07f25-8133-7395-43d5-2f389be06c32.png)

次にSOCIAL ACCOUNTS->Social applicationsのAddをクリックし、以下のように入力します。
Provider: Github
Name: Github
Client id: Githubで表示されたClient ID
Secret key： Githubで表示されたClient Secret
Sites: Available sitesの中のIPアドレスを選んで右ボタンをクリック
![スクリーンショット 2020-03-22 0.49.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/7d3fa0bb-20c5-c3ee-42cf-1243a3b9b174.png)

登録が終わったら、右上のVIEW SITEからGalaxyのトップページに戻り、管理ユーザーからログアウトしてから右上のログインをクリックします。
![スクリーンショット 2020-03-22 0.52.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/c4bc4eda-ada4-7e6f-2e4f-1f6c5bc55303.png)
OctocatのアイコンをクリックするとGithubの連携確認画面が表示されるので、Authorizeボタンを押すとログインできます。

これでローカルAnsible Galaxyの準備は完了です。

#試してみる
サンプルのコレクションとPlaybookを作って実行してみます。

##コレクション作成
以下コマンドを実行し雛形を作成します。Githubユーザー名(=Galaxyのログイン名)はNamespaceとして使われます。

```bash
$ ansible-galaxy collection init <Githubユーザー名>.sample_collection
```
以下のような構造でディレクトリ・ファイルが作成されます。

```
.
└── ussvgr
    └── sample_collection
        ├── README.md
        ├── docs
        ├── galaxy.yml
        ├── plugins
        │   └── README.md
        └── roles
```
適当なロールを作成

```bash
$ cd ussvgr/sample_collection/
$ mkdir -p roles/sample_role/tasks
$ mkdir -p roles/sample_role/meta
$ vi roles/sample_role/tasks/main.yml
$ vi roles/sample_role/meta/main.yml
```
```roles/sample_role/tasks/main.yml
---
  - name: say hello
    debug:
      msg: "Hello World!"
```
```roles/sample_role/meta/main.yml 
galaxy_info:
  author: ussvgr
  description: sample role
```
galaxy.ymlを適宜編集してから、以下コマンドを実行しtar ballを作成します。

```bash
$ ansible-galaxy collection build
```

出来上がったtar ballはGalaxyのメニューのMy ContentからAdd Contentでアップロードします。
![スクリーンショット 2020-03-22 1.17.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/e816f68b-b558-6542-fdc0-9b247a23ccc1.png)

##Playbook作成
AWX(Ansible Tower)で実行する場合、collections/requirements.ymlを以下のように作成することで自動でGalaxyからコレクションを取得してくれます。

```collections/requirements.yml
---
collections:
  - ussvgr.sample_collection
```
取得したコレクション内のロールを実行するには以下のようなPlaybookを作成します。

```site.yml
---
- hosts: all
  tasks:
    - name: import roles
      import_role:
        name: ussvgr.sample_collection.sample_role
```

##AWX設定
設定->ジョブ内のプライマリー GALAXY SERVER URLにDockerホストのIP:ポートを設定、ロールとコレクションのダウンロードを有効にしておきます。
![スクリーンショット 2020-03-22 1.54.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/84a3b683-e005-a71b-34e2-7ac19eefbc5c.png)

これで作成したPlaybookを実行すると、
![スクリーンショット 2020-03-22 2.03.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/a3b0b734-a766-ad48-0656-66869378f917.png)
ローカルのAnsible Galaxyからコレクションを取得して実行してくれました。

#終わりに
ちゃんと使う場合はPostgreSQLコンテナのPGDATAボリュームを永続化すればいいのかな？

社内でのPlaybookの共有・再利用方法を悩んでいましたが、ちょっと道筋が立ちそうです。
コレクションについてはもっと勉強せねば。