Edited at

AnsibleでChocolateyを使ってWindowsアプリをインストールする

More than 3 years have passed since last update.


はじめに

前回でAnsibleを使ってWindowsを操作する準備はできた。

今回は実践として、Windows用のパッケージマネージャChocolateyのインストールと、Chocolateyを使ったアプリケーションのインストールを行いながら、AnsibleがWindowsに対してできることを見ていくことにする。

環境は前回と同じ、Ansible 1.7.1でWindows 8.1 Updateを操作している。

使用しているインベントリファイルを再掲する。


hosts

[windows]

10.0.2.172

[windows:vars]
ansible_ssh_user=<Windows側のユーザ名>
ansible_ssh_pass=<Windows側ユーザのパスワード>
ansible_ssh_port=5986
ansible_connection=winrm



win_chocolateyモジュール(Ansible 1.9以降)

Ansible 1.9よりExtras Moduleとしてwin_chocolateyモジュールが追加された。

そのため、この文書の次項以降の作業は不要となった。

2015-06-27追記: Windows側にChocolatey 0.9.9以降がインストールされた場合、chocolateyの仕様変更にAnsible 1.9.2までに同梱されているwin_chocolateyモジュールが対応できておらず正常に終了しない。簡単な対処としてはwin_chocolateyモジュールをdevelにあるものに差し替えることである。

# curl https://raw.githubusercontent.com/ansible/ansible-modules-extras/devel/windows/win_chocolatey.ps1 -o /usr/lib/python2.7/site-packages/ansible/modules/extras/windows/win_chocolatey.ps1

# curl https://raw.githubusercontent.com/ansible/ansible-modules-extras/devel/windows/win_chocolatey.py -o /usr/lib/python2.7/site-packages/ansible/modules/extras/windows/win_chocolatey.py

以下のようなplaybookでWindowsアプリをインストールできる。

Chocolatey自体も最初にwin_chocolateyモジュールを使った時に自動的にインストールされる。


site.yml

- hosts: windows

tasks:
- win_chocolatey: name={{ item }}
with_items:
- SourceTree
- sysinternals


Windowsに対して使用できるAnsibleモジュール

現状、Ansibleに用意されたモジュールのほとんどがWindowsに対して使用することができない。使用できるのは公式ドキュメントによると、

および、Windows用に追加されたモジュール

2016-02-27追記: Ansible 2.0時点ではwin_*モジュールはもっと大量に増えている。

他にdebug等、操作する側でしか処理が行われないモジュールは使用できることを確認している。

つまり現状、Windows環境にファイルを受け渡す方法が、どこか適当なWebサーバにアップロードしてからwin_get_urlでダウンロードする以外にないようだ。

(SSHサーバやrsyncサーバなどがWindows側に立っていたりはしない前提で)

アプリの設定ファイルなんかも作りたければ、templateやlineinfile、ini_fileで作った設定ファイルをWebサーバにアップロードしてからwin_get_urlでダウンロードしろ、あるいはこれらのモジュールで動的に作ったPowerShellスクリプトをscriptで流し込め、ということになるのだろう。


chocolateyのインストール


rawモジュールを使用する

使用できるモジュールが上記の通りだけ、ということはrawモジュールが大活躍するに違いない、というわけでまずrawモジュールを使用する。

まずChocolatey公式の、PowerShellを使ってインストールする時に実行するコマンドを流してみる。

(見やすいようにコマンドと出力を1行開けている)

# ansible windows -i hosts -m raw -a 'iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))'

10.0.2.172 | FAILED | rc=1 >>
'iex' is not recognized as an internal or external command,
operable program or batch file.

エラーになった。

結局試した限りどんなPowerShellコマンド(「コマンドレット」と呼ぶ)もrawモジュールで流すとエラーになる、という結論になった。

2016-02-27追記: いつからなのかは調べていないが、Ansible 2.0.1で試す限りPowerShellコマンドがエラーにならず実行されるようだ。上のコマンドも-aの囲みを""にすれば通る。

今度はコマンドプロンプトからChocolateyをインストールする時に実行するコマンドを流してみよう。

# ansible windows -i hosts -m raw -a '@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString(\"https://chocolatey.org/install.ps1\"))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin'

10.0.2.172 | success | rc=0 >>
(以下省略)

というわけでこちらでは問題なくChocolateyをインストールできた。


scriptモジュールを使用する

rawモジュールでできないPowerShellコマンドを実行したければscriptモジュールを使えば良い。

上記のPowerShell用のインストールコマンドを書いたps1ファイルを作る。


chocolatey.ps1

iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))


そしてscriptモジュールで流し込む。

# ansible windows -i hosts -m script -a 'chocolatey.ps1'

10.0.2.172 | success >> {
"changed": true,
"rc": 0,
"stderr": "",
"stdout": (以下省略)

問題ない。

scriptモジュールには、ファイルがある時には実行しないcreatesオプションがあるので試してみる。

# ansible windows -i hosts -m script -a 'chocolatey.ps1 creates=C:\ProgramData\chocolatey\bin\chocolatey.exe'

10.0.2.172 | success >> {
"changed": true,
"rc": 0,
"stderr": "",
"stdout": (以下省略)

「"changed": true」になっている、ということは効いていない。

ファイルがない時には実行しないオプションremovesも同様であった。

ここで期待した通りのことをしたければwin_statモジュールを使用する。

Playbookを作って実行する。


site.yml

- hosts: windows

tasks:
- win_stat: path=C:\ProgramData\chocolatey\bin\chocolatey.exe
register: file_info
- script: chocolatey.ps1
when: file_info.stat.exists == false

# ansible-playbook -i hosts site.yml

PLAY [windows] ****************************************************************

GATHERING FACTS ***************************************************************
ok: [10.0.2.172]

TASK: [win_stat path=C:\ProgramData\chocolatey\bin\chocolatey.exe] ************
ok: [10.0.2.172]

TASK: [script chocolatey.ps1] *************************************************
skipping: [10.0.2.172]

PLAY RECAP ********************************************************************
10.0.2.172 : ok=2 changed=0 unreachable=0 failed=0

今度は期待通り「skipping」になった。


Windowsアプリのインストール

Chocolateyのパッケージインストール用のコマンドであるcinstはコマンドプロンプトでも実行できるのでrawモジュールを使うことができる。

先程のPlaybookに追加して実行することにする。

2015-06-27追記: Chocolatey 0.9.9以降、cinstに-yオプションを付けないとすぐにインストールしてくれなくなった。それより前のバージョンでは-yは必要ない。


site.yml

- hosts: windows

tasks:
- win_stat: path=C:\ProgramData\chocolatey\bin\chocolatey.exe
register: file_info
- script: chocolatey.ps1
when: file_info.stat.exists == false
- raw: cinst {{ item }} -y
with_items:
- SourceTree
- sysinternals

# ansible-playbook -i hosts site.yml

PLAY [windows] ****************************************************************

GATHERING FACTS ***************************************************************
ok: [10.0.2.172]

TASK: [win_stat path=C:\ProgramData\chocolatey\bin\chocolatey.exe] ************
ok: [10.0.2.172]

TASK: [script chocolatey.ps1] *************************************************
skipping: [10.0.2.172]

TASK: [raw cinst {{ item }}] **************************************************
ok: [10.0.2.172] => (item=SourceTree)
ok: [10.0.2.172] => (item=sysinternals)

PLAY RECAP ********************************************************************
10.0.2.172 : ok=3 changed=0 unreachable=0 failed=0

問題なくアプリケーションをインストールできた。


まとめ

Ansible 1.7.1時点での、今回使用したモジュールのまとめ。


  • rawモジュールではPowerShellコマンドを流すとエラーになり、コマンドプロンプトで実行できるものだけが実行できる。PowerShellコマンドを流すにはscriptモジュールを使用する。

  • scriptモジュールのcreatesオプション、removesオプションはWindowsに対しては利用できない。win_statモジュールを利用して同等のことはできる。