月別: 2014年12月

AWS EC2 のインスタンスにvagrant + Jenkins + chef-solo + serverspec を入れてインフラCIする

最近インフラの話題が熱いです。
chefを使ってインフラ構築がコード化(Infrastructure as Code)ができるようになった事でプログラムソースと同じく、サーバーの構築手順などもコードとしてgitなどで管理できるようになりました。

そうするとプログラマたちがJenkins等のCIツール(継続的インテグレーション)で自動テストしているのもやりたくなってきます。
インフラのCIにおいてVagrantやserverspecといったツールがこれらのCI環境の整備を後押しした事もあり、インフラCIの手順などの記事も増えて、とてもワクワクしています。

(参考)
Vagrant + Chef Solo + serverspec + Jenkins でサーバー構築を CI

CIする所をサーバーにしたい

いろんな記事では基本的にMacOSXにjenkins vagrant virtualbox chef を入れての作業になってます。
また、vagrant-awsなどを使用してもそれは同じで、あくまでもローカルのMACからawsを操作する内容になっています。

インフラがコード化されて、gitで管理されたとなるとやっぱり共同で開発していきたいと思うのですが、インフラCIの為にMAC/Windowsのそれぞれのクライアントに「vagrant」「jenkins」「chef」・・・ と入れてもらうのは敷居が高いしちょっとなんだかなぁと思ってました。
そこで、今回はAWSのEC2インスタンスにvagrant + Jenkins + chef-solo + serverspecを入れてCIする環境を構築したいと思います。

ツールのおさらい

vagrant
仮想サーバーの構築や破棄をコマンドで行える仮想環境構築ツール。CIする上で一番うれしいのは立ち上げたサーバへのSSHなどの接続まわりのすべてを面倒みてくれるところかな、と思います。

chef
サーバー構築の自動化フレームワークツールです。「冪等性を保証する」というポリシーで作成します。冪等性とは1回行っても複数回行っても結果が常に同じであるような事をいいます。冪等性を保証する事で、単なるサーバー構築を行うツールではなく、何度実行してもサーバーが設定どおりの状態となる事を保障できるツールとなります。

serverspec
サーバにApacheが入っているか、80ポートが空いているか、など、意図した通りにサーバが稼働しているかどうかをチェックできるツールです。

jenkins
CI(継続的インテグレーション)ツールです。jenkinsを使う事で「テスト」や「ビルド」、はては「デプロイ」まで自動化する事ができます。

ゴール

・gitのリポジトリの特定ブランチにpushがあると
・jenkinsが捕捉して、ビルドを実行
・vagrantにてEC2インスタンスを立ち上げてchefを流してサーバー構築
・サーバー構築が完了するとserverspecでサーバー状態をチェック
・結果をjenkinsで管理

jenkinsサーバーの構築

ともあれ、CIを行う為のサーバーが必要なのでEC2でインスタンスを立ち上げます。
今回はCentOSを使いました。
こちらのインスタンスにvagrant、Jenkins、chef-solo、serverspecをインストールしていきます。

EPELリポジトリを追加

wget http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh epel-release-6-8.noarch.rpm

パッケージをインストール。いらないものもあると思うので適当に割愛してください

yum install -y make gcc gcc-c++ xinetd openssl-devel libcurl-devel zlib-devel readline-devel bzip2-devel curl-devel libmcrypt libmcrypt-devel sudo redhat-lsb yum-utils yum-plugin-priorities yum-plugin-fastestmirror yum-plugin-security
yum install -y mlocate bind-utils dstat elinks multitail nc nmap rsync traceroute tree unzip wget which zip zsh mosh uuid telnet
yum install -y autoconf automake bison bzip2 gettext-devel libtool libxml2-devel libxslt-devel libyaml-devel libffi-devel ncurses-devel patch
yum install -y git iftop tig python-pip rpm-build ImageMagick ImageMagick-devel jq
yum install -y java-1.7.0-openjdk java-1.7.0-openjdk-devel

AWS CLIのインストール(任意)

pip install awscli

chefのインストールとchefで入ったrubyにpathを通します

curl -L https://www.opscode.com/chef/install.sh | bash
echo "export PATH=\"/opt/chef/embedded/bin:\$PATH\"" > /etc/profile.d/chef_embedded.sh
source /etc/profile.d/chef_embedded.sh

chefで入ったgemでserverspecなどをインストール

/opt/chef/embedded/bin/gem install rake --no-ri --no-rdoc
/opt/chef/embedded/bin/gem install serverspec --no-ri --no-rdoc
/opt/chef/embedded/bin/gem install ci_reporter --no-ri --no-rdoc
/opt/chef/embedded/bin/gem install unf --no-ri --no-rdoc

vagrantのインストール

wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.6.5_x86_64.rpm
rpm -i vagrant_1.6.5_x86_64.rpm
vagrant plugin install vagrant-aws
vagrant plugin install unf
vagrant plugin install vagrant-serverspec
vagrant plugin install vagrant-global-status
vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box

jenkinsのインストール

sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum -y install jenkins

各種設定

以下のようなディレクトリ構成とする事にします

vagrant/
Vagrantfile
spec/
spec_helper.rb
hogehoge/
httpd_spec.rb
chef/cookbooksとかいろいろ

chefのレシピを配置

テストしたいchefのレシピたちを配置します。割愛

serverspecの設定

spec_helper.rbはこんな感じです

require 'serverspec'
require 'pathname'
require 'net/ssh'
include SpecInfra::Helper::Ssh
include SpecInfra::Helper::DetectOS

httpd_spec.rbはこんな感じです
とりあえずポート80が空いてるかどうかのテスト

require '../spec_helper'
describe port(80) do
it { should be_listening }
end

vagrantの設定

mkdir /path/to/vagrant
cd /path/to/vagrant
vi Vagrantfile

以下はサンプル。
vagrant-awsの設定とprovisionとして「シェルの実行でchefをインストール」「chef-soloの実行」「serverspecの実行」を行っています。

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
# usage vagrant up --provider=aws
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "dummy"
config.vm.provider :aws do |aws, override|
aws.access_key_id = 'xxxxxxxxxxxxx'
aws.secret_access_key = 'xxxxxxxxxxxxx'
aws.region = 'ap-northeast-1'
aws.instance_type = 't2.micro'
aws.ami = 'ami-xxxxx'
aws.security_groups = ['sg-xxxxxx','sg-xxxxx']
aws.keypair_name = 'xxxx'
aws.ssh_host_attribute = :private_ip_address
override.ssh.username = 'root'
override.ssh.private_key_path = '/path/to/key'
aws.subnet_id = 'subnet-xxxxxx'
aws.associate_public_ip = 'true'
aws.tags = { 'Name' => 'CI' }
end
# shell exec
config.vm.provision :shell, :path => "curl -L https://www.opscode.com/chef/install.sh | bash"
# chef exec
config.vm.provision "chef_solo" do |chef|
chef.cookbooks_path = ["../chef/cookbooks", "../chef/site-cookbooks"]
chef.roles_path = "../chef/roles"
chef.run_list = ["role[xxxxxxxx]"]
end
# serverspec
config.vm.provision :serverspec do |spec|
spec.pattern = '../spec/hogehgoe/*_spec.rb'
end
end

vagrant-awsにおけるAWSのアクセスキーや秘密鍵。セキュリティグループの設定等は割愛。

注意点としてprovision shellを実行する時にno ttyと出る時があります。
これは立ち上げるAMIの/etc/sudoers 内のDefaults requiretty行をコメントアウトすれば解決するかもしれません。
立ち上げるインスタンス用のAMIはこれらvagrantが接続してprovisionができる環境を整えたものであるといいかと思います。(例えばchefが入ってるAMIですとchefのインストールをvagrantから行う必要がなくなります)

vagrantで仮想サーバーが立ち上がり、chefをインストールし、chefを流し、serverspecでテストまで流れるかテストします。

vagrant up --provider=aws

もう一度chefとかを流したりしたい場合は以下のコマンドで実行できます。

vagrant provision

任意のprovisionのみ実行したいときは以下のような感じになります。

vagrant provision --provision-with serverspec

確認できたら消します。ちなみにAWSでは1分でも立ちあげると1時間ぶんの料金がかかりますので注意です。

vagrant destroy

jenkinsの設定

jenkinsからはvagrantコマンドを実行したりする予定ですが、root権限が必要なのでsudo設定等を行います

visudoで以下を追記

Defaults:jenkins !requiretty
jenkins ALL=(ALL) NOPASSWD:ALL

Defaults requirettyとかあったらコメントアウトしておきます。

jenkinsの起動

/etc/init.d/jenkins start

http://サーバーIP:8080 でjenkinsさんがみえます。

jenkinsにgitプラグインを入れる

[Jenkinsの管理]-> [プラグインの管理] -> [利用可能タグ]でGit Pluginをインストールします。

新規ジョブを作成

[新規ジョブ作成]->[フリースタイル・プロジェクトのビルド]を選択してプロジェクト名を適当に入力して作成します。

プロジェクトの設定(git)

作成したプロジェクトをクリックしてプロジェクトの画面に進み[設定]をクリックします。

ソースコードの管理でgitを選択して監視を行うリポジトリとブランチを設定します。
今回はmasterブランチです

プロジェクトの設定(ビルド・トリガ)

ビルド・トリガを設定します。
通常であればgitのリポジトリ側からpushがあった場合にjenkinsに通知する事でビルドが実行されるのがよいのですが、簡単な方法として、jenkins側から定期的にgitリポジトリに更新を確認しにいくポーリングを設定しました。

この設定ですと、10分に1回更新を確認しにいき、pushされていればビルドを実行する設定になります。

プロジェクトの設定(ビルド)

最後にビルド設定です。
ビルドは「シェルの実行」を選択します。
ビルド実行でvagrantを立ち上げ、テストして落とすという処理となりますので以下のようなコードとしました。
このときのシェルはjenkinsユーザーが実行するので適宜sudo等をつけてあげる必要があります。

cd /path/to/vagrant
sudo vagrant up || RET1=$?
sudo vagrant provision --provision-with serverspec > /tmp/serverspec.tmp
cat /tmp/serverspec.tmp
SPEC=`cat /tmp/serverspec.tmp | grep "0 failures" | wc -l`
RET2=0
if [ $SPEC -ne 1 ]; then RET2=1 ; fi
rm -f /tmp/serverspec.tmp
sudo vagrant destroy
if [ $RET1 -ne 0 ]; then exit $RET1 ; fi
if [ $RET2 -ne 0 ]; then exit $RET2 ; fi
exit 0

途中ややこしい事になっていますがvagrant-serverspecプラグインでのserverspecの結果は成功/失敗によらず正常終了となるので、serverspecが失敗した場合はjenkinsでFailとなるようにすこし調整しています。

最終的にはこんな感じになりました。(gitの部分はエラーになってますが)

この設定でchefのレシピをCIできるようになりました。

ディスプレイが・・

まぶしい(+_+)と感じること、みなさんはありませんか?
私は普段、結構ディスプレイの輝度を下げて作業してます。
いつかのシーマガでも取り上げられてましたが、目にも良くないですし。

夜寝る前にパソコンとかやるとよく寝れないと聞くので、部屋を暗目にしてあまりパソコンとかせずに本読んだりしてます。けどやっぱりパソコン触りたい時があります。

それでもできるだけ目に刺激がないようにディスプレイの輝度を最小にしているんですけど、それでもディスプレイがまぶしい(+_+)

ターミナルとかエディタとかは背景色を設定できたりするので黒目に設定しています。
問題はブラウザで、WEBページの背景が白かったり明る目の色の時、どうしようもありません。
Googleで検索したら背景真っ白でまぶしい(+_+)

なので、快適な睡眠のためにちょっと工夫しました。

ディスプレイのカラーを反転させる

Macは環境設定>アクセシビリティ>ディスプレイでカラーを反転できます。
これ使ったら基本白い部分の多いサイトとか書類とか見る時は結構暗めにできます!
↓こんな感じ


 

黒くなったけど画像とか見難いですね。
しかもこの設定してると今まで黒かったターミナルとか真っ白です。

とかなんとか遊んでたらイイ感じのGoogleChromeのプラグインを見つけました。

Change Colors

こちら、背景とか文字を指定した色に変えてくれます。
こんな感じで設定できます。

 

 

これを使うとさっきの画面が

こんな感じになります。画面は暗くなって、画像なんかはそのまま表示されるので、そんなに見難くない。

別に見やすくはないですけど個人的には全然大丈夫です。

ページ毎にこれを適用できるので、必要ないページはそのままの色で見れます。

 

これで寝る前にネットしても熟睡できそう。

iPhoneから日本語名のファイルを添付してメールを送るには

こんにちは。WEBエンジニアのyuchiです。

日本語文字化け対策のために、iPhoneに日本語ファイルを添付してメールを送信するというのを
最近行いましたので、その時のことを書きます。

iPhoneで写真を撮ると自動的に日時の名前で保存されますが、保存された写真のファイル名を
変更することはできませんでした。

今まで試みたことなかったので知らなかったです…ちなみにAndroidはファイル名を変更できました。

ファイル名を変更できないとわかったので、iPhoneiTunesに同期してPCに保存してある日本語名の
ファイルを保存し、iPhoneのメールアプリからファイルを添付しましたが、今度はimage.pngという名前に
自動変換される始末・・・

DropBoxや、Evernoteで保存してある日本語名のファイルをコピーして、ペーストしても
自動的にやはりimage,pngに変換されました。

恐るべしiPhone・・・結果的には色々試行錯誤しましたが、iPhoneの機能で日本語ファイルを添付して
メールを送信するということができませんでした。

どうやったかといいますと、iPhonegmailアプリを起動、googleドライブから日本語名のファイルを選択し添付で送信。

これで問題なく日本語名のファイルで送信され、文字化けテストができました。

ちなみに有料ですが、GoodReaderを使うと日本語名のファイルを保存できるようです。

豆知識くらいに知っておくと便利かもしれません。

javascriptのオブジェクトについて

プログラマのkinuです。普段よく使いますがあまり理解せずに使ってたjavascriptのオブジェクトについて調べました。
javascriptオブジェクト指向プログラムをサポートした言語です。
PHPなどのクラスを実装し、オブジェクトを生成して動作させるクラスベースのオブジェクト指向ではなく、プロトタイプベースのオブジェクト指向です。プロトタイプというのがどういうものを指してるのかまだ理解できてないですが、とりあえずオブジェクトからオブジェクトを生成して動作させるということはなんとなくわかりました。

生成のしくみ

javascript のオブジェクト生成の単純な例です。

[code]
var A = function (x) {
this.x = x;
};
A.prototype.x = 0;
var a = new A(1);
[/code]

[コード1]

http://d.hatena.ne.jp/maeharin/20130215/javascript_prototype_chain
の記事を参考にインスペクタでのぞきながら自分なりに図にまとめました。

figure1

[図1]

四角はオブジェクト、矢印はプロパティです。点線の矢印は構造と直接関係ない補助的なものです。
この図から実際使うオブジェクトのほかにオブジェクトを生成するオブジェクト(コンストラクタ)とベースになるオブジェクト(プロトタイプ)があることがなんとなくわかります。
このままだとわかりづらいので図にまとめると、

figuire2

[図2]

つまり、コンストラクタをnewするとprototypeプロパティにもったオブジェクトをもとにオブジェクトを生成してくれるということです。あとついでにコンストラクタの処理を生成したオブジェクトで実行してくれます。

__proto__ってなに?

プロパティprotoは内部プロパティprototypeの値でプロトタイプをもってます。
[図1]でいうと、aA.prototypeを、A.prototypeObject.prototypeをもっています。
プロパティ(またはメソッド)を使うときにこのprototypeをたどって探索します。これをプロトタイプチェーンといいます。

オブジェクトがオブジェクトを生成する

あらためて[図1]をみると[図2]の形がけっこうみつけられます。
aをみてみるとAA.prototypeをもとにつくられています。AFunctionFunction.prototypeをもとにつくられ、A.prototypeObjectObject.prototypeをもとにつくられてます。
この仕組みでオブジェクトが生成されていることがわかりますね。

Object.create()

コンストラクタをnewしてオブジェクトを生成する方法のほかにもオブジェクトを生成する方法もあります。それはObject.create()です。
以下のようにして使います。

[code]
var a = Object.create(Object.prototype);
a.x = 1;
[/code]

[コード2]

これで[コード1]とほぼ同じオブジェクトが生成されます。
「ほぼ」といっているのはコンストラクタから生成したときに自動に設定されるプロパティconstructorがこれでは設定されません。これはinstanceofで使われているプロパティなので使い方によっては注意が必要です。
実は[コード2]はObject.create()がなくても
[code]
var a = {};
a.x = 1;
[/code]

[コード3]

と書いても同じことができます。あれ、Object.create()いらないんじゃ…と思っちゃいそうですが、既存のオブジェクトからオブジェクトをつくるときに役立ちます。
例えば,

[code]
var a = {};
a.x = 1;
var b = Object.create(a);
b.y = 1;
[/code]

[コード4]

のようにすると既存のオブジェクトを簡単に拡張できます。

まとめ

今回はjavascriptのオブジェクトの生成について調べました。
クラスを作らなくてもオブジェクトが作れるのはプロトタイプベースの利点なのかなあなんてふんわり理解できたような気がします。このあたりは実際使うとときがきて実感するんじゃなかろうか。
またクラスベースっぽいふるまいもできるのでそれぞれの特性を生かして使いわけて実装できるという点はすごくいいなと思いました。その分いろいろと知っておく必要はありますが。
あと、今回プロトタイプチェーンという概念がでてきましたがスコープチェーンというのもあるらしいです。まだまだ知らないことも多いですがこれからも暇をみつけて勉強していきたいです。

参考にしたWebページ

Android ブラウザで PHP によるファイルダウンロードが出来ない件

Android ブラウザで PHP によるファイルダウンロードが出来ない件

SSL にて、PDF や ZIP ファイルをダウンロードする場合、SSL の証明書が有効でないとダウンロードは出来ません。
 この場合、.pdf ファイルに直接アクセスしても、ダウンロードは出来ません。

② POST 送信で 「Content-Disposition:attachment」を出力する場合、再び GETで同じURLにリクエストを送信するとのことです。
GET 送信で、リクエストさせる方法で実装するしかないようです。
「Content-Disposition:inline」にした場合、POST→GET の送信はされませんでしたが、ファイル名(filename)が指定出来ませんでした。
よって、この方法もダメでした。

参考URL
http://zhzrzkz.blogspot.jp/2012/05/android.html
http://stackoverflow.com/questions/4674737/avoiding-content-type-issues-when-downloading-a-file-via-browser-on-android
https://code.google.com/p/android/issues/detail?id=1978

これらによると、AndroidのブラウザがPOSTメソッドでサーバにリクエストし
て、サーバからContent- Disposition:attachmentなヘッダを受け取ると、再び
GETメソッドで同じURLにリクエストを送信するとのことです。
また、この動作はPCのブラウザとは違うのですが、バグでは無いようです。

対応方法としては、POSTメソッドとGETメソッドで処理を変えるとか、フォーム
データの内容が見えてもよいのなら画像をダウンロードする URLには、GETメ
ソッドでリクエストする等がありそうです。
 

人気記事ランキングプラグイン「WordPress Popular Posts」と「WP-PostView」の機能比較

ブログサイトでは人気記事ランキング(アクセスランキング)を実装しているサイトがほとんどですよね。
そこでWordPressで人気記事ランキングを実装する際にお世話になるプラグインを2つ比較してみました!

WordPressを1から構築する人向けに拡張性という所を重視しています!
初心者は何も考えずに「WordPress Popular Posts」を使うのが無難です。

WordPress Popular Posts

デイリー・ウィークリー・総アクセスのアクセス数を表示できるのが魅力的。
タイトルとリンク、投稿日などの表示カスタマイズが可能。
拡張すれば、サムネイルも表示できます。

すごく便利なので、ある程度のサイトであれば「WordPress Popular Posts」を使っておけば間違いないかと思います。

デメリット
・カスタムフィールドの値やカテゴリ名などが取得できず拡張性が少ない。

上記が意外とデメリットとしては大きいです。
カテゴリなど入っている場合はデザインの変更をお願いすることがあるので、
もう少し拡張できればといつも思う所です。

WP-PostViews

カスタムフィールドの値やカテゴリ名が取得できるプラグインです。
アクセス数がカスタムフィールドの「views」に保存されるので
get_postsの取得が可能。

[code]<?php
$popular = get_posts(
array(
‘post_type’ => ‘post’,
‘meta_key’ => ‘views’,
‘orderby’ => ‘meta_value_num’,
‘order’ => ‘ASC’
)
); ?>

  • <a href=”<?php echo get_the_permalink($p->ID); ?>”><?php echo get_the_title($p->ID); ?>

[/code]

取得方法は上記みたいな感じです。

とても拡張性が高くサムネイルの表示などもwordpressを独自で組まれる方はとても扱いやすいプラグインです。

デメリット
・総アクセス数しかカウントできない

純粋なウィークリーじゃなければ
古い記事は表示されないという方法で代用策として下記の様なことも参考にできます。

WP-PostViewsとかJetpack Post Viewsで出力する記事を徹底的にカスタマイズしちゃう

結局よく使うのは「WordPress Popular Posts」

最初は総アクセスでよくても今後週間やデイリーに変更したいという要望がとても多いので回収のことを考えると
「WordPress Popular Posts」で実装します。

ブログサイトの場合は完全に「WordPress Popular Posts」
よくある質問をアクセス順で並べるという際は「WP-PostViews」を使用しています。

個人的にはWP-PostViewsが週間やデイリーに対応すれば完璧なのになと思うばかりです。

© SEEDS Co.,Ltd.