EIPをAnsibleで管理する


#はじめに
AnsibleにはAWSのリソースを操作できるモジュールが豊富に用意されています。

今回は、ec2_eipモジュールを利用して取得済みのEIPをEC2インスタンスにAnsibleでアサインしてみます。

#やること
- EC2インスタンスに取得済みEIPをアサイン

##ポイント
ec2_eipモジュールでは、対象のEC2インスタンスIDが必要となりますが、IDをAnsibleのYAMLに書きたくないので、EC2インスタンス名からIDを取得する実装とします。


#前提
- AWS関連のモジュール実行にはbotoが必要です。
- credential情報は環境変数か`aws configure`でセットしてある必要があります。
- EIPは取得済みであること。


下記リソースを前提に進めます。

- VPC
	- AnsibleVPC
- 取得済みEIP
	- 54.xx.xx.xx
	- 52.xx.xx.xx
- EC2インスタンス
	- test01
		- 54.xx.xx.xxをアサイン
	- test02
		- 52.xx.xx.xxをアサイン



#sample

##ディレクトリ構成

```bash:ディレクトリ構成
site.yml
roles/
|--eip/
|  |--tasks/
|  |  |--main.yml
hosts/aws    #inventory
host_vars/
|--localhost.yml
```

##inventory

AWSリソース関連モジュールはすべてlocalhostで実行するので、下記のようなインベントリファイルを用意します。

```bash:hosts/aws
[aws]
localhost
```

##vars

こんな感じに変数を定義します。今回はhost_varsで定義しました。

```yaml:host_vars/localhost.yml
---
my_vars:
  aws:
    common:
      region: ap-northeast-1
    vpc:
      name: AnsibleVPC    # ターゲットのVPC名
    eip:
      - ip: 54.xx.xx.xx
        device: test01 #ec2 instance name
      - ip: 52.xx.xx.xx
        device: test02 #ec2 instance name
```

##Role

まずVPCを特定するためにidが必要ですが、[こちら](http://qiita.com/tomohiko_isobe/items/c245bedfa6966305eb10)と同様、VPC名でidを取得します。

ec2_remote_factsモジュールでEC2インスタンス名からIDを取得し、set_factモジュールで`{EC2インスタンス名:ID}`のディクショナリを生成します。

後続タスクではこのディクショナリから対象のEC2インスタンスIDを取得します。

```yaml:roles/eip/tasks/main.yml
---
- name: vpc_id取得
  ec2_vpc_net_facts:
    region: "{{ my_vars.aws.common.region }}"
    filters:
      "tag:Name": "{{ my_vars.aws.vpc.name }}"
  register: vpc_net_fact
  when: my_vars.aws.vpc is defined
  check_mode: no

- debug: var=vpc_net_fact

- name: ec2 facts取得
  ec2_remote_facts:
    region: "{{ my_vars.aws.common.region }}"
    filters:
      vpc_id: "{{ vpc_net_fact.vpcs[0].id }}"
      "tag:Name": "{{ item.value.tags.Name }}"
  with_dict: "{{ my_vars.aws.ec2 }}"
  register: ec2_fact
  when: my_vars.aws.eip is defined

- name: ec2 dict作成
  set_fact:
    ec2_dict: >-
      {%- set dict = {} -%}
      {%- for i in range(ec2_fact.results|length) -%}
      {%-   set _ = dict.update({ec2_fact.results[i].instances[0].tags.Name: ec2_fact.results[i].instances[0].id}) -%}
      {%- endfor -%}
      {{ dict }}
  when: my_vars.aws.eip is defined

- name: associate an elastic IP with an instance
  ec2_eip:
    region: "{{ my_vars.aws.common.region }}"
    device_id: >-
      {%- set id = ec2_dict[item.device] -%}
      {{ id }}
    ip: "{{ item.ip }}"
  with_items: "{{ my_vars.aws.eip }}"
  register: eip
  when: my_vars.aws.eip is defined

- debug: var=eip
```

##site.yml
```YAML:site.yml
---
- name: eip
  hosts: localhost
  connection: local
  roles:
    - role: eip
```

##実行
```bash:Command
$ ansible-playbook -i hosts/aws -l localhost site.yml
```


#まとめ
マネジメントコンソール上では管理しづらいEIPですが、Ansibleで管理すればどのEIPがどのインスタンスにアサインされているのか分かりやすくなると思います。

#参考
- [VPCをAnsibleで作成する](http://qiita.com/tomohiko_isobe/items/c245bedfa6966305eb10)
- [IAMユーザをAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/5ae6f15f52a2d20e2635)
- [AWSのセキュリティグループをAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/7342b8ba874d997c5c6c)
- [EC2をAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/163b23d5a0e566aaa159)
- [ec2_group_factsモジュールをAnsible2.2で使えるようにする](http://qiita.com/tomohiko_isobe/items/8684b4dc8f99793e5cf8)
- [RDSをAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/7ce42217e177f0c6b7ec)