以前Windowsの開発環境をscoopで構築しているということを書きました。
その際に、scoopを継続的に使っていくためのツールScoopPlaybookを書いたことに触れました。 今回はそのScoopPlaybookの紹介です。
概要
- ScoopPlaybookというPowerShellモジュールを作った(2年近く使っている)
- scoopで何をインストールするかをYAML定義して使える
- Scoop-PlaybookコマンドでYAML通りに実行される
- 使い心地は、Ansible PlaybookのYAML定義とコマンドにインスパイアされている
scoop使っていて、YAMLでインストールするツールを定義したい方は使ってみてください。
目指す姿
私は普段からOS環境を壊すことをアリと考えています。 ただし壊すからには再構築にコストをなるべくかけたくないため、対象のマシン上で再構築がコマンド1つでできるようにしています。 macOSはHomebrewやdefaultsをAnsible Playbookで構築し、UbuntuはAnsible Playbookで構築しています。
Ansible Playbookを使うことで、ほどよく緩くいい感じの目指す姿が可能になります。
- 利用する開発ツールをYAMLに定義して
- 何度実行しても同じ結果に収束させる
例えばHomebrewでインストールする場合は次のように定義できます。
# roles/homebrew/tasks/main.yaml - name: 'homebrew packages installation' homebrew: name: '{{ item.name }}' state: "{{ item.state|default('present') }}" with_items: "{{ homebrew_packages }}" # roles/homebrew/vars/main.yaml homebrew_packages: - name: autoconf - name: awscli - name: aws-iam-authenticator - name: azure-cli # and so on....
一度定義してしまえばツールを定義に追加したり、アンインストール ( state: "absent" ) を指定するだけとメンテナンスが非常に簡単です。
site.ymlを置いたルートパスでいつも同じコマンドを実行するだけで、YAML定義通りに環境が構築されます、便利。
$ ansible-playbook -i hosts site.yml
sudoが必要な操作 (become) なら、実行時に入れるだけです。
ansible-playbook -i hosts site.yml --ask-become-pass
WSLとの相性もよく、気軽に環境を壊してサクッと作り直すことがコストでなくなります。
自分の環境にどんなツールをいれているかを説明することがふとしたときにあるのですが、定義によって、いつでも確認したり継続的に変更をかけたり、場合によっては他人に共有できるのは個人的に好みです。
WindowsでAnsiblePlaybook のようなアプリケーションインストール基盤を作る
環境の再構築はWindowsでもたびたび行います。(OSいれなおしでなくてもリセットはやりますよね)
scoopを使っていくことに決めたとき、コマンドの羅列地獄になるのは嫌だと思いました。 しかしAnsibleをWindows localhostに実行はサポートされていないので、Ansible Playbookのような定義とインストールを提供することにしました。(WSLからAnsible実行するというのはナシ派) その晩にザクっと書いたのがScoopPlaybookというPowerShell Moduleです。
あんまり使い方とか書いていないので、どのような利用をするのか紹介します。
scoop の通常のインストール
例えば、scoopでgow、jq、time、unzipをインストールする場合、コマンドラインで次のように実行するでしょう。
scoop install gow jq time unzip
あるいは、次のようにコマンドを分けてもいいでしょう。
scoop install gow scoop install jq scoop install time scoop install unzip
アンインストールもコマンドラインで制御できます。
scoop uninstall gow
入っているツールはscoop listで見えますが、ほかの環境や再構築、追加インストールをするときはいちいち考えるの嫌になります。
ScoopPlaybook で定義からインストールする
ScoopPlaybookはAnsible Playbookでやっていたのと同じ目指す姿を提供します。
- 利用する開発ツールをYAMLに定義して
- 何度実行しても同じ結果に収束させる
利用方法はAnsible Playbookに合わせています。
ルートパス/site.ymlに利用するroleのYAML定義し、ルートパス/roles/バケット/tasks/main.ymlにツールをYAML定義したら、- ルートパスで、
Scoop-Playbookコマンドを実行すると、Scoopバケットやツールが定義通りにインストール/アンインストールされる
YAMLで定義して、コマンド1つで実行します。ただそれだけです。 実際にどうやるのかイメージしにくいので利用例を見てみましょう。
利用例
先ほどのmainバケットのツールをScoopPlaybookでYAML定義してインストールしてみましょう。 ScoopPlaybookモジュールとYAM解析モジュールをインストールします。PowerShell 5.1以降で動作します。
PS> Install-Module ScoopPlaybook -Scope CurrentUser PS> Install-Module "PowerShell-Yaml" -Scope CurrentUser
適当にルートパスを切ります。
md ./begin cd ./begin
まずは、インストールしたいアプリの定義YAMLをルートパス/roles/main/tasks/main.ymlに定義します。
PS> mkdir roles/main/tasks PS> New-Item roles/main/tasks/main.yml PS> vim roles/main/tasks/main.yml
- name: "Install main tools" scoop_install: state: present bucket: main name: - gow - jq - time - unzip
インストールするロールを指定したYAML定義site.ymlをルートパスにおきます。
PS> New-Item site.yml PS> vim site.yml
今回のロールはmainなのでこれを1つ指定します。
name: Windows Setup roles: - main
早速定義をドライランしてみましょう、次のコマンドをsite.ymlのパスで実行します。
PS> Scoop-Playbook -Mode check
scoopのバケットを更新して (scoop update) 、ツールがインストールされるか実行計画を確認できます。
PRE [scoop : status] *************************************************************** [o] skip: [run with 'check' mode] [o] skip: [prerequisiting availability] [o] skip: [updating buckets] [o] check: [scoop-update: Updating Scoop...] [o] check: [scoop-update: Updating 'main' bucket...] [o] check: [scoop-update: Scoop was updated successfully!] [o] skip: [status checking] [o] skip: [scoop-status: Scoop is up to date.] [o] check: [scoop-status: Updates are available for:] .... 省略 PLAY [Windows Setup] *************************************************************** TASK [main : Install main tools] *************************************************** [!] check: [scoop_install: gow] => Installed: No [!] check: [scoop_install: jq] => Installed: No [!] check: [scoop_install: time] => Installed: No [!] check: [scoop_install: unzip] => Installed: No
問題なければインストールします。Modeパラメーターを省略するか、-Mode runを明示的に付けると実行します。
PS> Scoop-Playbook
PRE [scoop : status] *************************************************************** .... 省略 PLAY [Windows Setup] *************************************************************** TASK [main : Install main tools] *************************************************** [!] changed: [scoop_install: gow] => Installed: No Installing 'gow' (0.8.0) [64bit] Loading Gow-0.8.0.exe from cache Checking hash of Gow-0.8.0.exe ... ok. Extracting dl.7z ... done. Running pre-install script... Linking ~\scoop\apps\gow\current => ~\scoop\apps\gow\0.8.0 .... 省略 'gow' (0.8.0) was installed successfully! [!] changed: [scoop_install: jq] => Installed: No Installing 'jq' (1.6) [64bit] .... 省略 'jq' (1.6) was installed successfully! [!] changed: [scoop_install: time] => Installed: No Installing 'time' (0.2018.07.25) [64bit] .... 省略 [!] changed: [scoop_install: time] => Installed: No Installing 'time' (0.2018.07.25) [64bit] .... 省略 'time' (0.2018.07.25) was installed successfully! Notes ----- Please use 'timecmd' instead of 'time' in cmd.exe. [!] changed: [scoop_install: unzip] => Installed: No Installing 'unzip' (6.00) [64bit] .... 省略 'unzip' (6.00) was installed successfully!
再度実行しても同じ結果に収束します。 もし更新があれば更新してくれます。
PS> Scoop-Playbook
Scoop-Playbook PRE [scoop : status] *************************************************************** .... 省略 PLAY [Windows Setup] *************************************************************** TASK [main : Install main tools] *************************************************** [o] skip: [scoop_install: gow] => gow 0.8.0 [o] skip: [scoop_install: jq] => jq 1.6 [o] skip: [scoop_install: time] => time 0.2018.07.25 [o] skip: [scoop_install: unzip] => unzip 6.00
何かの理由でscoopコマンドを直接インストールすることもあるでしょう、そんな時は定義に一行足せばいいだけです。
もしscoopコマンドで誤ってアンインストールしても、Scoop-Playbookを実行すれば元通りです。
Scoopで管理したいツールを定義通りに実行する。それができます。
普段の利用例
私はScoopPlaybookを使ってYAML定義をしてGitHubにおいています。
参考に私が普段使っているリポジトリを置いておきます。ルートパスはこのリポジトリの./envs/windows/パスです。
https://github.com/guitarrapc/local-provisioner/tree/master/envs/windows
そのため、環境構築するときは次のコマンドを実行しています。
git clone https://github.com/guitarrapc/local-provisioner.git cd local-provisioner/envs/windows . ./prerequisites.ps1 sudo Scoop-Playbook
ツールの追加や削除をしたいときは、定義のYAMLを修正してgit commit/pushするだけです。
バッチファイルやスクリプトではないので、どのように動作するかは考えず、ツールをYAMLに並べるだけなのはメンテの面で作ってよかったと思っています。
実際これなしでscoopとかいやです。
できること
ScoopPlaybookは次の操作が可能です。これしかできないです。
scoop_bucket_install: バケットの追加、削除scoop_install: ツールのインストール、アンインストール
バケットの追加、削除
scoopは任意のGitHubリポジトリなどをバケットにできます。scoop bucket add xxxx
ScoopPlaybookもscoop_bucket_installでバケットの追加、削除をサポートしています。
例えばextrasバケットを追加する場合、次のように書けます。
- name: "Install extras bucket" scoop_bucket_install: state: present bucket: extras
extrasバケットは特別扱いされていますが、自分のGitHub URLを指定したい場合は次のようになります。
- name: "Install guitarrapc bucket" scoop_bucket_install: state: present bucket: guitarrapc source: https://github.com/guitarrapc/scoop-bucket.git
もしも追加したバケットを消したいならstateにabsentを指定します。 (sourceは省略できます)
- name: "Uninstall guitarrapc bucket" scoop_bucket_install: state: absent bucket: guitarrapc
それぞれのキーは、scoop bucketコマンドに合わせてあります。
- state: presentかabsentを指定
- bucket: 対象のバケット名を指定
- source: GitHubなどのバケットURLを指定
ツールのインストール、アンインストール
scoopはバケットからツールのインストール、アンインストールができます。scoop install xxxx
ScoopPlaybookもscoop_installでツールのインストール、アンインストールをサポートしています。
- name: "Install main tools" scoop_install: state: present bucket: main name: - gow
先ほど追加したgowをアンインストールするなら次のように書けます。
- name: "Uninstall main tools" scoop_install: state: absent bucket: main name: - gow
それぞれのキーは、scoop installコマンドに合わせてあります。
- state: presentかabsentを指定
- bucket: 対象のバケット名を指定
- name: ツールを配列で指定
すでにインストールされているツールに更新がある場合は、Scoop-Playbook実行時に更新してくれます。便利。
管理者権限で実行したい
scoopはユーザー権限が基本でーとか言いますが、ツールによってはFiddlerのように管理者権限がないとインストールできないものもあります。 そんなときはsudoコマンドです。
sudoコマンドをインストールしておいて(scoop install sudo相当)
- name: "Install main tools" scoop_install: state: present bucket: main name: - sudo
Scoop-Playbookをsudoつきで実行すればokです。
sudo Scoop-Playbook
まとめ
一人で使ってて満足していたんですが、WinGetが出てきて未来はどうなるかと楽しみにしています。 ただ、WinGetはこのままいくとこういうYAML定義に関しては手を出さず、誰かが何か作るのでしょう。
アンインストールやUAC考慮がない、今のWinGet触る気はありませんが、WinGetを触る将来が来たらこういうツール書きたくなる日も来るでしょう。 ただ、その時はたぶんPowerShellでは書かない気がする。