Ansibleでチームの開発環境(Visual Studio Code & IntelliJ)を構築する

前の環境では、自席の非力なWindows PCと、強力なLinuxサーバがあったので、Dockerで開発環境イメージを作成して、新規チーム参加者でも同じ設定で直ぐに作業を始められるようにしていた。

* IDEはEclipse。
* プラグインをinstallIUオプションで追加。
* フォーマッタ等の設定した結果が保存されるファイルを特定し、その設定を出力するワークスペース作成シェルを作成。

現在は、自席にそこそこなスペックのCentOS 7 PCがあり、サーバは自由に使えるマシンがなかったので、勉強を兼ねてAnsibleを使って開発環境を構築することにした。
また、これを機会にIDEはIntelliJに変更。

# Ansibleのインストール

```
# yum install epel-release
# yum install ansible
# ansible --version
ansible 2.8.1
```

# [Ansible Role: IntelliJ](https://github.com/gantsign/ansible-role-intellij)

まずは同じような悩みを解決してくれていないか探してみると、[GantSign Ltd.](https://gantsign.com/)という会社がこれを公開してくれていました。プラグインの追加もフォーマッタの設定も行なってくれるので、まさにドンピシャという感じ。

## インストール
[Ansible Galaxyのページ](https://galaxy.ansible.com/gantsign/intellij-plugins)を見るとインストールコマンドが載っているので、それをそのまま実行。

```
$ ansible-galaxy install gantsign.intellij-plugins
$ ls ~/.ansible/roles/
gantsign.intellij
```

でも後々の事を考え、Ansible Galaxyのお作法(?)に従って必要なRoleをファイルに記載して起きます。

```yml:./requirements.yml
- src: gantsign.intellij
```
そうすれば他の人からひと目で、どんな外部Roleを利用しているか判るし、

```
ansible-galaxy install -r requirements.yml
```
複数のRoleでも一発でインストールできますしね。


## Playbookの作成
Ansible Role: IntelliJのREADME.mdを参考にパラメータを設定。

```yml:./site.yml
- hosts: develops
  pre_tasks:
    - include: tasks/java.yml
  roles:
    - role: gantsign.intellij
      intellij_default_maven_home: '/usr/share/apache-maven'
      users:
        - username: "{{ ansible_user_id }}"
          intellij_jdks:
            - name: '1.8'
              home: '/usr/lib/jvm/java-1.8.0-openjdk'
            - name: '11'
              home: '/usr/lib/jvm/java-11-openjdk'
          intellij_default_jdk: '11'
          # 使用しないプラグイン(まだSubversionを使うシチュエーションがある)
          intellij_disabled_plugins:
            - com.intellij.uiDesigner
            - org.jetbrains.android
            - TestNG-J
            - hg4idea
            - AntSupport
            - DevKit
          # フォーマッタ(最近は2スペースのインデントが好み)
          intellij_codestyles:
            - name: GoogleStyle
              url: https://raw.githubusercontent.com/google/styleguide/gh-pages/intellij-java-google-style.xml
          intellij_default_codestyle: GoogleStyle
          # 追加するプラグイン
          intellij_plugins:
            - Lombook Plugin
            - in.1ton.idea.spring.assistant.plugin
```
* ansible_user_idは[Ansibleのドキュメント](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html)に記載されていた変数で、ansible-playbookコマンドの--userオプションで指定されたリモートユーザ名になる。ユーザを指定する意味は、IntelliJの本体はデフォルトで/opt/idea配下に格納されるが、設定やプラグインはユーザホーム配下に格納されるから。

* 不要なプラグインは、手動でインストールしたIntelliJの/.Idea*/config/disabled_plugins.txtを参考にすればプラグインIDが判明する。

* 一方、追加するプラグインのIDは、README.mdにxmlstarletを使ってリストを取得する方法があるものの、イマイチ良く判らなかったので、GitHub上のプラグインのソースから抜き出した。例えばLombokなら[plugin.xml](https://github.com/mplushnikov/lombok-intellij-plugin/blob/master/src/main/resources/META-INF/plugin.xml)のidタグの値を使用する。

あと念のためJavaとMavenのインストール定義を以下に記載する。

```yml:tasks/java.yml
- name: install java
  become: yes
  yum:
    name: '{{ packages }}'
  vars:
    packages:
      - java-11-openjdk-devel
      - java-11-openjdk-jmods
      - java-11-openjdk-src
      - java-11-openjdk-javadoc
- name: alternatives java
  become: yes
  command: alternatives --set java java-11-openjdk.x86_64
- name: install maven repository
  become: yes
  get_url:
    url: http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo
    dest: /etc/yum.repos.d/epel-apache-maven.repo
- name: install maven
  become: yes
  yum:
    name: apache-maven
```

## IntelliJの日本語化
自分も含め英語が苦手な人も多い(?)と思うので、[Pleiades](http://mergedoc.osdn.jp/#pleiades.html)で日本語化。

Ansibleはpre_tasks → roles → tasksの順で処理が行われるとのことで、tasksに追加。

* Ansible Galaxyから取得したRoleとRoleの間に処理を挟みたい場合、どうすればいいのかという疑問は保留。

```yml:./site.yml
  tasks:
    - name: IntelliJ日本語化
      stat:
        path: "{{ ansible_user_dir }}/{{ ansible_local.intellij.general.user_dirname }}/config/jp.sourceforge.mergedoc.pleiades"
      register: stat_pleiades
    - name: IntelliJ日本語化
      get_url:
        url: http://ftp.jaist.ac.jp/pub/mergedoc/pleiades/build/stable/pleiades.zip
        dest: /tmp/pleiades.zip
      when: not stat_pleiades.stat.exists
    - name: IntelliJ日本語化
      unarchive:
        src: /tmp/pleiades.zip
        dest: /tmp
        remote_src: yes  
      when: not stat_pleiades.stat.exists
    - name: IntelliJ日本語化
      shell: mv /tmp/plugins/jp.sourceforge.mergedoc.pleiades "{{ ansible_user_dir }}/{{ ansible_local.intellij.general.user_dirname }}/config/"
      when: not stat_pleiades.stat.exists
    - name: IntelliJ日本語化
      stat:
        path: "{{ ansible_user_dir }}/{{ ansible_local.intellij.general.user_dirname }}/config/idea64.vmoptions"
      register: stat_idea64_vmoptions
    - name: IntelliJ日本語化
      shell: cp "{{ ansible_local.intellij.general.home }}/bin/idea64.vmoptions" "{{ ansible_user_dir }}/{{ ansible_local.intellij.general.user_dirname }}/config/"
      when: not stat_idea64_vmoptions.stat.exists
    - name: IntelliJ日本語化
      lineinfile:
        dest: "{{ ansible_user_dir }}/{{ ansible_local.intellij.general.user_dirname }}/config/idea64.vmoptions"
        line: "{{ item }}"
      with_items:
        - -Xverify:none
        - "-javaagent:{{ ansible_user_dir }}/{{ ansible_local.intellij.general.user_dirname }}/config/jp.sourceforge.mergedoc.pleiades/pleiades.jar"

```
* IntelliJのユーザホーム配下に作成されるフォルダは固定じゃないが、gantsign.intellijがansible_local.intellij.general.user_dirname変数にフォルダ名を格納してくれるので、それを使う。
* Pleiadesのインストール手順だとGUIでVMオプションを指定するのだが、この設定が格納される~/.Idea*/config/idea64.vmoptionsファイルはインストール直後は存在しなかった。ファイルを丸々コピーしてしまうのは、IntelliJのデフォルト設定が変更になった場合とかを考えるとモヤモヤするので、いろいろ足掻いてみた。するとIntelliJのインストールフォルダ配下にオリジナルのidea64.vmoptionsが存在していたので、これをコピーしてVMオプションを追記した。

# [Ansible Role: Visual Studio Code](https://github.com/gantsign/ansible-role-visual-studio-code)

GantSign Ltd.では、こちらも公開してくれていましたので、同様の手順でRoleを追加しました。

```yml:./site.yml
    - role: gantsign.visual-studio-code
      users:
        - username: "{{ ansible_user_id }}"
          visual_studio_code_extensions:
            - ms-ceintl.vscode-language-pack-ja
            - jebbs.plantuml
            - editorconfig.editorconfig
          visual_studio_code_settings: {
            "plantuml.render": "PlantUMLServer",
            "plantuml.server": "http://www.plantuml.com/plantuml",
          }
```
* visual_studio_code_settingsにはキーバリュー形式で設定値を指定する。ちょっと昔は設定ファイルが生のJSONファイルだったからキーも簡単に判ったけど、今はGUIになって判らない、とか思ったけど、[Editor: Tab Size]とかの項目名にカーソルを当てると歯車アイコンが現れて、キーが取得できた。

* 仕事で使うならplantuml.serverは自前で建てたPlantUML Serverを指定した方が無難かも。


# 実行
あとはhostsファイルの[develops]セクションに適用対象のホストを記載して、Ansibleの実行中にパスワードが尋ねられないようにして、コマンドを実行。

```
ansible-playbook -i hosts -u ${user} site.yml
```

* 自分はssh-copy-idで公開鍵を適用対象ホストに配布、かつリモートユーザがパスワードなしでsudoできるようにしました。このあたりはAnsible Vaultを調査する必要がありそう。