Ansibleでのインストールの目的別逆引き

Ansible版もかいてみた備忘録です。[Chef版はこちら](https://qiita.com/smallpalace/items/ecbf751ac565227125ad)。

#####**・ yumでインストールする**

```
- name: install cloud-init
  yum: 
    name: cloud-init
    state: present

```
最新を入れたい、再度実行したときにupdateされたい場合はstateをlatestにする。 
他のオプションは公式マニュアルか`ansible-doc yum`で確認できる。  
[yum - Manages packages with the yum package manager — Ansible Documentation](http://docs.ansible.com/ansible/latest/yum_module.html)

#####**・OS種別に応じて分岐インストールさせる**

```
- block:
  - name: install apache yum
    yum:
      name: "{{ item }}"
      state: "{{ apache_package_state }}"
    with_items:
      - httpd
      - httpd-devel
      - mod_ssl
      - openssl-devel
    tags: install-apache
  - name: start and enable service of apache redhat
    service:
      name: httpd
      state: started
      enabled: yes
    tags: run-enable-httpd
  when:
    - ansible_os_family == 'RedHat' 

- block:
  - name: install apache apt
    apt:
      name: "{{ item }}"
      state: "{{ apache_package_state }}"
    with_items:
      - apache2
      - apache2-utils
    tags: install-apache
  - name: start and enable service of apache debian
    service:
      name: apache2
      state: started
      enabled: yes
    tags: run-enable-apache2
  when:
    - ansible_os_family == 'Debian'

```

fact（≒ohai）を使うのでPlaybookで`gather_facts`をnoにしてると使えない（デフォルトはyes）
blockで複数タスクをまとめてwhenで条件定義可能。リストで定義した条件はandでつなげられる。
[Ansibleを支えるfact: プラットフォームの情報を取得 — そこはかとなく書くよん。](http://tdoc.info/blog/2013/08/23/ansible_fact.html)

#####**・ 複数のサービスを無効化する**

```
- name: disable services
  service:
    name: "{{ item }}"
    enabled: no
  with_items:
    - auditd
    - lvm2-monitor
    - mdmonitor
    - atd
    - NetworkManager
  tags: disable-services
```

　
#####**・ ファイルをダウンロードして配置する**

```
- name: download foo.conf
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    mode: 0440

```

#####**・ version指定でインストールする**

```
- name: install one specific version of Apache
  yum:
    name: httpd-2.2.29-1.4.amzn1
    state: present
```

#####**・ yumでグループインストールする**

```
- name: install the 'Development tools' package group
  yum:
    name: "@Development tools"
    state: present

- name: install the 'Gnome desktop' environment group
  yum:
    name: "@^gnome-desktop-environment"
    state: present
```
Group名つかうときは頭に`@`つける、GroupIDつかうときは頭に`@^`つけることになってる模様。
[RHEL 7.1のyumでパッケージグループをインストールする - 覚え書き | OSS Fan](http://ossfan.net/memo/archives/2015/11/03220620.html)


#####**・ 特定のyumリポジトリから入れる(有効なリポジトリの制御）**

```
- name: install the latest version of Apache from the testing repo
  yum:
    name: httpd
    enablerepo: testing
    state: present
```
オプションとしてはdisablerepoもあるようなのでbaseから入るのが困る時によさそう。


#####**・ tarアーカイブから展開していれる**
make install参照のこと
#####**・ make installしたい**

[Ansible、ソースインストールする際のPalybookの書き方 · Goldstine研究所](https://blog.mosuke.tech/entry/2014/11/16/153223/)

```
   ## emacsのソースファイルを取得済みか確認
   - name: check exist emacs source file
     command: ls -l {{src_dir}}/{{emacs_ver}}.tar.gz
     ignore_errors: True
     register: result1

   ## emacsのソースファイル取得。ただし、すでに取得済みならスキップ
   - name: get emacs source file
     command: chdir={{src_dir}} wget http://mirror.jre655.com/GNU/emacs/{{emacs_ver}}.tar.gz
     when: result1|failed

   ## emacsのソースインストールを解凍
   - name: get emacs source file
     command: chdir={{src_dir}} tar xvf {{emacs_ver}}.tar.gz
     when: result1|failed

   ## emacsがインストールされているか確認
   #  確認基準はemacsコマンドのpathが通っているかで判断した
   - name: check emacs install
     command: which emacs
     ignore_errors: True
     register: result2

   ## emacsのインストール。ただしすでにemacsがインストールされいたらスキップ
   - name: expand emacs src
     command: chdir={{src_dir}} tar xvf {{emacs_ver}}.tar.gz
     when: result2|failed

   - name: comfigure emacs
     command: chdir={{src_dir}}/{{emacs_ver}} ./configure
     when: result2|failed

   - name: make emacs
     command: chdir={{src_dir}}/{{emacs_ver}} make
     when: result2|failed

   - name: install emacs
     command: chdir={{src_dir}}/{{emacs_ver}} make install
     when: result2|failed
 
```


#####**・ gemをinstallしたい**

```
# Installs version 1.0 of vagrant.
- gem:
    name: vagrant
    version: 1.0
    state: present

# Installs latest available version of rake.
- gem:
    name: rake
    state: latest

# Installs rake version 1.0 from a local gem on disk.
- gem:
    name: rake
    gem_source: /path/to/gems/rake-1.0.gem
    state: present
```
[gem - Manage Ruby gems — Ansible Documentation](http://docs.ansible.com/ansible/latest/gem_module.html)
[gem moduleにrbenvでインストールしたgemを使おうとしたらハマった - Qiita](http://qiita.com/itiut@github/items/3e1aaa4f2b5d95efb319)


#####**・ gitからinstallしたい**

```
# Example just ensuring the repo checkout exists
- git:
    repo: 'https://foosball.example.org/path/to/repo.git'
    dest: /srv/checkout
    update: no
```
[git - Deploy software (or files) from git checkouts — Ansible Documentation](http://docs.ansible.com/ansible/latest/git_module.html)

#####**・ install直後に変数を読み込みなおしたい**

要するにホスト名やIPアドレスを付け替えた値とってから設定ファイルに埋め込みたいとかそんなだけども、

ohaiのreloadをnotifiesでimmediatoryでやるかんじの記事は検索ででてこず
ホスト名は`"{{ inventory_hostname }}"`つかえばよくて、
IPアドレスは`"{{ hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address'] }}"`という感じの模様。

[ansibleを学ぶ：vol03：実行中のホスト名を書き込む、変数の値に変数を使用する - 文系プログラマによるTIPSブログ](http://www.bunkei-programmer.net/entry/2014/07/08/011225)

#####**・ install直後にただちにサービスを起動したい**

`meta: flush_handlers`でいける模様です
http://docs.ansible.com/ansible/latest/meta_module.html

#####**・ 設定ファイルやパッケージファイルを配りたい**

[templates, lineinfile, copy, file などのモジュール](http://docs.ansible.com/ansible/latest/list_of_files_modules.html)を使いましょう。

```
# apacheの設定ファイルを置く例
$ vi roles/apache/tasks/main.cf
## templateモジュールで使用する変数を設定
vars:
    virtualhosts:
      - { port: 80, fqdn: site1.example.com, allow_override: True }
      - { port: 80, fqdn: site2.example.com, allow_override: False }

## templateタスクを定義
tasks:
    - name: set virtualhost conf
      template:
        src: 'virtual_hosts.conf.j2
        dest: '/etc/httpd/conf.d/virtual_hosts.conf
        owner: 'root'
        group: 'root'
        mode: 0644

$ vi roles/apache/templates/virtual_hosts.conf.j2
## templateモジュールで転送するテンプレートファイル
{% for host in virtual_hosts %}
<VirtualHost *:{{host_port }}>
    ServerName {{ host.fqdn }} 
    DocumentRoot /var/www/html/{{ host.fqdn }}/
    ErrorLog logs/{{ host.fqdn }}-error_log
    CustomLog logs/{{ host.fqdn }}-access_log common
{% if host.allow_override %}

    <Directory /var/www/html/{{ host.fqdn }}/>
        Options FollowSymLinks
        AllowOverride All
    </Directory>
{% endif %}
</VirtualHost>
{% endfor %}

$ cat /etc/httpd/conf.d/virtual_hosts.conf
## templateモジュールで設置されたファイル
<VirtualHost *:80>
    ServerName site1.example.com
    DocumentRoot /var/www/html/site1.example.com/
    ErrorLog logs/site1.example.com-error_log
    CustomLog logs/site1.example.com-access_log common

    <Directory /var/www/html/site1.example.com/>
        Options FollowSymLinks
        AllowOverride All
    </Directory>
</VirtualHost>
<VirtualHost *:80>
    ServerName site2.example.com
    DocumentRoot /var/www/html/site2.example.com/
    ErrorLog logs/site2.example.com-error_log
    CustomLog logs/site2.example.com-access_log common
</VirtualHost>
```

#####**・ yamlのシンタックスなど**

コメント
ハッシュ#から行末まではコメントして扱われますハッシュを文字列に含む場合はクォートで囲みます。

```
# comment
yum: name=httpd # comment
value: "#abc"
```

リスト
リスト（値が順に並んでいる集合。配列、シーケンスなど）は、ハイフン-を先頭に記述し、半角スペースを続けた後に値を記述します。
1行につき1要素を表します。1行で複数の要素を記述する場合は、角カッコ[ ]でリスト全体を囲み、要素をカンマ区切りで記述します。

```
- value1
- value2
上と下いみは同じ
[ value1, value2 ] # 1行で記述
```

ディクショナリ
ディクショナリ（キーと値のペアの集合。マップ、ハッシュなど）は、key: valueの形式で、
キーの後にコロン:をつけ、さらにスペースを入れたあとに値を記述します。
１行に１つのペアを記述します。1行で複数のペアを記述する際は波カッコ{ }でディクショナリ全体を囲み、
ペアをカンマ区切りで書きます。

```
key1: value1
key2: value2
key3: a b c
上と下いみは同じ
{ key1: value1, key2: value2, key3: a b c }
```

真偽値
真偽値（真または偽を表す、ブーリアン、ブール型など）には、いくつか記述方法があります。
true, on, yesは真、false, off, noは偽として扱われます。
いずれの値も小文字か大文字か先頭のみ大文字で記述可能。

```
# すべて真
become: True
become: ON
become: yes
# すべて偽
become: False
become: OFF
become: no
```

インデント
リストやディクショナリで、インデントを入れるとネストすることができます。
インデントはスペースで表現します。（2スペースがよく利用されます）
tabはインデントにはならないので注意してください。


#####**・ attributeの使い分け等、データをどう準備するかの話**

[順序というか優先順位がある](http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable)ので、初期値をデフォルトに、roleに依存するやつはroleに、
グループやホストに依存するのはgroup_vars,host_varsに、
ステージングとか環境依存のはvarsに入れてplaybookでvars_files指定、実行のタイミングで変えたかったらextra_vars指定という感じでしょうか。
http://dev.classmethod.jp/server-side/ansible/ansible-inventory-pattern/

暗号化するやつはansible-vault使うよう分けとくとよさそうです。
http://dev.classmethod.jp/server-side/ansible/ansible-vault-introduction/
https://qiita.com/yteraoka/items/de9da64ca2d9261b0292

#####**・ 特定のファイルに実行権限があったら処理をしたい**

```
- name: check if cloud provider is azure
  action: command [ -x /usr/sbin/waagent ]
  register: result
  ignore_errors: True
  tags: check-if-provider-is-azure
- name: disable NetworkManager on azure
  service:
    name: NetworkManager
    enabled: no
  tags: disable-NetworkManager-azure
  when: result|succeeded
```
[Conditionals — Ansible Documentation](http://docs.ansible.com/ansible/playbooks_conditionals.html)

#####**・暗号化データを含むファイルを配置する**

Vaultで暗号化した変数ファイルからSSL証明書をcopyモジュールで配置する例

###### インベントリファイルがある場所の`group_vars`の下にグループ名のディレクトリを掘って暗号化したい内容をまとめた変数ファイルを作成する

```
$ vi group_vars/groupname/enc.yml
$ ansible-vault encrypt group_vars/groupname/enc.yml 
New Vault password: 
Confirm New Vault password: 
Encryption successful
$ cat group_vars/jenkins/enc.yml 
$ANSIBLE_VAULT;1.1;AES256
64303539653563363931626265306565616533613265353134333863343361343435613236643663
```

###### 暗号化された内容を復号化して閲覧してみる

```
$ ansible-vault view group_vars/groupname/enc.yml 
Vault password: 
private_ssl_crt: |
  -----BEGIN CERTIFICATE-----
  MIIFETCCA/mgAwIBAgISBIGbwW4oIeZrJFCx8g4HI3EDMA0GCSqGSIb3DQEBCwUA
  MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
  ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzA4MDQxNDU0MDBaFw0x
  NzExMDIxNDU0MDBaMCIxIDAeBgNVBAMTF2lzYW8tamVua2luczAxLmlzYW8ubmV0
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8IWpeTk+s74o6nmK6BO
  8WRrfXQfj94YHrmzVAI8Ndy3NF0iPGLK4shR5a+UcLWGV2uBK3f1iLZyLPW4/1r4
～略～
private_ssl_key: |

  ygB58fRsMVTrPzQSHbfbNoQHjm5W55AdKf0rfCibattSR9jVTgNNUVElKESbbfcJ
  PoGunLDW3zl0AvfUJfFeBkg8ibdrBxVdyRyw3AqWEMmHAW5BNY9VwJfD98OPA1iR
  tYdlg1EPZ9PFX5/ZRJyXsxQ4
  -----END PRIVATE KEY-----

dbpass: "hogehoge"
```

###### taskを書く
`no_log`はansible-playbook実行時の標準出力に出ないように制御するもの。

```
$ vi rolename/tasks/main.yml
- name: copy ssl_cert(with vault)
  copy:
    content: "{{ private_ssl_crt }}"
    dest: '/tmp/server.crt'
  no_log: true
  tags: copy-sslcrt
 
- name: copy ssl_key(with vault)
  copy:
    content: "{{ private_ssl_key }}"
    dest: '/tmp/server.key'
  no_log: true
  tags: copy-sslkey
 
- name: copy dbpass
  copy:
    content: "{{ dbpass }}"
    dest: '/root/.mysql_pwd'
  no_log: true
  tags: copy-dbpass
```

###### playbookに`vars_files`を念のため指定する

```
# for jenkins
- name: Playbook for groupname
  hosts: all
  vars_files:
    - group_vars/groupname/pub.yml
    - group_vars/groupname/enc.yml
```

###### 実行する

```
$ ansible-playbook -i hosts -c local site.yml -C -D -vvv --ask-vault-pass
$ ansible-playbook -i hosts -c local site.yml -D -vvv --ask-vault-pass

```