Chefを利用してAndroidSDK本体のインストール及び特定AndroidSDKインストールを自動化させたいと思っていました。
が、指定したAndroidSDKのインストールの途中で利用許諾の承認が必要であり、単純にexecuteコマンドを利用してインストールが出来ませんでした。
調査するとexpectコマンドを使うと対話形式の入力が必要な処理を自動化出来るとのことで実際に実施する事が出来たいのでそのメモを記載します。
そもそもexpectコマンドとは?
- telnetやsshなどパスワード入力を求められるような処理を自動化出来る
- 同様にインストール時に許諾への同意などが必要なものも自動化させる事が出来る
前提
- Chef、Berkshelfなどはインストール済み
- ホストはMac OSX 10.9.3
- test-kitchenを利用。ドライバはvagrantを利用。
Chefやtest-kitchenの詳細は過去のブログを参考の事。
Berkshelf version3+Knife soloでnginx環境をVagrantに作ってみた話
[Chef]Berkshelfを利用したJenkinsクックブックを作成してserverspec+Kitchenでテストした話
参考
こちらのクックブックを参考にさせて頂きました。
gildegoma/chef-android-sdk
Github
置きました。
toshihirock/AndroidSDK
- Ubuntuのテストはしてません
- URLやAndroidSDKのバージョンは適宜変更してください。(そのうちattribute化したい。。。)
準備
クックブック作成します。
$knife cookbook create android -o .
AndroidSDKを利用する為にJavaのインストールが必要ですが、サードパーティのクックブックを利用
します。
また、AndroidSDKのダウンロード、展開の為にopscodeのarkというクックブックを利用します。
サードパーティのクックブックを使う為にBerksheflを利用する準備をします。
$berks init .
利用するためにmetadata.rbに追記を行います。
$cd android
$vi metadata.rb
name 'android'
maintainer 'YOUR_COMPANY_NAME'
maintainer_email 'YOUR_EMAIL'
license 'All rights reserved'
description 'Installs/Configures android'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.1.0'
depends "ark"
depends "java"
また、test-kitchenを使ってプロビジョニングを行うのでその為のファイルを作成します。
$kitchen init
既にBerkshlefで.kitchen.ymlが作成済みの場合にはコンフリクトしますが、yを入力して鵣川書きします。
今回、試験ははCentOSのみに今回はするため、.kitchen.ymlの一部をコメントアウトします。
$vi .kitchen.yml
編集。
platforms:
#- name: ubuntu-12.04
- name: centos-6.4
AndroidSDK本体のダウンロード、展開
まずはAndroidSDK本体のダウンロード、展開までのレシピを書きます。
本来はURLやパスはattributesの値とすべきですが、とりあえずベタ書きします。
$vi recipes/default.rb
編集。
include_recipe 'java'
%w{unzip expect}.each do |pkg|
package pkg do
action :install
end
end
ark 'android' do
url 'http://dl.google.com/android/adt/22.6.2/adt-bundle-linux-x86_64-20140321.zip'
path '/usr/local/android'
end
URLはAndroidのサイトをみて確認してください。(ビット数に応じてダウンロードするzipが違いますが、今回は判定処理は割愛して64bitで確認)
試験環境の準備
VMの起動。
$kitchen create
VMにChefやBerkshelfのインストール、及びレシピの適用を行います。
$kitchen setup
状態を確認します。
$kitchne list
SSH接続して確認してみます。
$kitchen login
$ll /usr/local
lrwxrwxrwx. 1 root root 20 Jun 9 14:30 android -> /usr/local/android-1
expectコマンドを使ってみる
Chefのコードを書く前に正しく動作出来るかVMでコマンドを実行して確認してみます。
$kitchen login
$sudo su
$cd /usr/local/android/sdk/tools
$vi expectTest.sh
確認用のシェルスクリプトを編集します。
#!/bin/bash
expect -c '
spawn /usr/local/android/sdk/tools/android update sdk --no-ui --filter android-17
set timeout 1800
expect {
-regexp "Do you accept the license.*" {
exp_send "y\r"
exp_continue
}
}
'
ざっくり説明します。
- spawn:実際に実行させたいコマンド
- set timeout:expectの実行を許容する時間。短すぎるとコマンドの途中で強制終了してしまう。
- regrexp:どの文字列が表示されたら入力を自動的に行うかの正規表現。今回の場合、利用規約のDo you accept …という文字列が表示された時に入力を行う事を示す。
- exp_send:regrexpで合致する文字列が表示された時に自動入力する文字列。
- exp_continue:これを指定しないと自動入力したあと復帰出来ないっぽいです。
実行権限を付与して、実行してみます。
$chmod a+x expectTest.sh
$./expectTest.sh
Chefのレシピでexpectコマンドを実行する
成功すればこれをChefのレシピに落とし込みます。
$exit
$vi recipes/default.rb
レシピに追記します。
script 'Install Android SDK' do
android_version="android-17"
interpreter 'expect'
not_if { ::File.exists?("/usr/local/android/sdk/#{android_version}") }
code <<-EOF
spawn /usr/local/android/sdk/tools/android update sdk --no-ui --filter #{android_version}
set timeout 1800
expect {
-regexp "Do you accept the license.*" {
exp_send "y\r"
exp_continue
}
}
EOF
end
テストも書きます。今回はserverspecを利用します。
Gemfileに追加します。
$echo "gem \'serverspec\'" >> Gemfile
$mkdir -p test/integration/default/serverspec/localhost/
$vi test/integration/default/serverspec/localhost/default_spec.rb
テストを書きます。
require 'serverspec'
include Serverspec::Helper::Exec
include Serverspec::Helper::DetectOS
describe command('which java') do
it { should return_exit_status 0 }
end
describe command('ls /usr/local/android/sdk/platforms/android-17') do
it { should return_exit_status 0 }
end
色々実験したので一度、VM環境を削除します。
$kitchen destroy
その後、VMの作成、Chefの適用、serverspecのテストを実施します。
$kitchen test
問題なく完了すればOKです。