Vagrant + DigitalOcean + Ansibleで環境構築
ものすごく今更ながら、実践Vagrantを見ながら、Vagrantを試してる。
- 作者: Mitchell Hashimoto,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/02/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (5件) を見る
ついでに気になってたDigitalOceanも試したかったので、 VagrantとSSDなVPS(Digital Ocean)で1時間1円の使い捨て高速サーバ環境を構築する - Glide Note - グライドノート を参考に、DigitalOceanにVagrant+Ansibleで環境を構築する方法を試したので、メモ。
Vagrantのインストール
Download Vagrant - Vagrantからバイナリをダウンロード。
Ansibleのインストール
プロビジョニングには今回Ansibleを使用。インストールはpipから。
pip install ansible
DigitalOcean Pluginのインストール
標準のproviderではDigitalOceanは存在しないが、Pluginが既にあるので、インストール。
https://github.com/smdahlen/vagrant-digitalocean
vagrant plugin install vagrant-digitalocean
MacだとDigital OceanのAPIを叩くためには追加で下記をインストールする必要があるみたい。
brew install curl-ca-bundle
インストール後、.zshrc等に環境変数をセット
export SSL_CERT_FILE=/usr/local/opt/curl-ca-bundle/share/ca-bundle.crt
DigitalOceanのアカウント作成
DigitalOceanからアカウントを作成。
アカウント作成後、管理画面からssh keyの登録とAPI keyの発行を行う。
Vagrantfileの作成
インスタンスは最小プラン(512MB)、RegionはSingaporeの構成で作成する想定。 注意点としては、「provider.client_id」、「provider.api_key」、「provider.ssh_key_name 」をssh keyの登録やAPI keyの発行で確認したものにきちんと設定すること。
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure('2') do |config| config.vm.hostname = "digital-ocean-test" config.vm.provider :digital_ocean do |provider, override| override.ssh.private_key_path = '~/.ssh/id_rsa' override.vm.box = 'digital_ocean' override.vm.box_url = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box" provider.client_id = 'API key発行時に確認したClient ID' provider.api_key = 'API key発行時に確認したAPI key' provider.region = 'Singapore 1' provider.size = '512MB' provider.ssh_key_name = 'ssh key登録時に登録したssh key name' end config.vm.provision :ansible do |ansible| ansible.playbook = "provision_vagrant.yml" # playbookファイル名 ansible.host_key_checking = false end end
playbookの作成
ansibleでprovisionするためにplaybookを作成。 provisoningの内容は、実践Vagrantの例の通り。
playbookのファイル名は「provision_vagrant.yml」で作成。
- hosts: default user: root tasks: - apt: pkg=apache2 update_cache=yes state=latest - file: path="/var/www" state=absent - file: src="/vagrant" dest="/var/www" state=link
DigitalOceanではユーザ名がrootで作成されるので、「user」を「root」にすること。
Ansibleでは通常provisoning先をINVENTORY FILEに記載する必要があるが、DigitalOcean等、ローカル以外の環境に作成する場合は、IPアドレスが作成後に決まる為、事前にINVENTORY FILEを用意することができない。
Vagrantではこの問題を解消するために、INVENTORY FILEを指定しない場合は、自動でINVENTORY FILEを作成し、それを使用してprovisioningを行ってくれる。*1
vm名をVagrantfileで指定しない場合は、「default」で生成されるので、「hosts」についても「default」を指定。
あと、実践Vagrantにならって、index.htmlも用意しておく。
<strong>Hello</strong>
インスタンスの作成
上記まで用意できたら、あとはVagrantを実行するだけ、providerとしてDigitalOceanを指定して起動。
vagrant up --provider=digital_ocean
起動後はsshでアクセス
vagrant ssh
後はブラウザでアクセスして下記のように表示されれば、OK
使い終わったら、destroyでインスタンスを破棄。
vagrant destroy
参考
http://blog.glidenote.com/blog/2013/12/05/digital-ocean-with-vagrant
https://github.com/smdahlen/vagrant-digitalocean
https://docs.vagrantup.com/v2/provisioning/ansible.html
Erlang 17rc1をMacにインストールしてみた
R16B まではwxWidgetsの問題でMacでobserver等が動かず、悲しい思いをしていたが、17rc1で試して見たらあっさり動いたのでメモ*1。
環境
Mac OSX 10.9.1 (Marvericks)
Erlang 17.0-rc1
wxWidgetsのインストール
wxWidgetsをhomebrewでインストール。現時点だと3.0.0が入るはず。
brew install wxmac
Erlangのインストール
Erlangのソースはerlang-users.jpがミラーを用意してくれているので、そちらからダウンロード。
configure オプションもerlang-user.jpを参考に。違いはwxをオプションを有効にしているだけ。*2
./configure --enable-darwin-64bit --disable-hipe --enable-vm-probes --with-dynamic-trace=dtrace --with-wx --prefix=/opt/local/erlang/R17rc1
あとはそのままmake, make installするだけ。
make sudo make install
observerの起動
erl -s observer start
でobserverを起動。
Bitbucket ミートアップ東京に行ってきた
以下メモ
How we use Bitbucket to build Bitbucket
Erik van Zijstさん
英語だったので、全然聞き取れなかった。サーセン。
質問
githubに勝てる?
UIについて
- 製品一つに対して、一人のデザイナーが付いている。そのデザイナーと相談してUIを決めてる
- 他のAtlassian製品とできるだけデザインを併せている。またUI用のフレームワークがある。
百を超えるプライベートレポジトリがある。レポジトリを簡単に検索・グルーピングできる機能ってある?
- 他のユーザからも問い合わせがある
- issueも上がっているけど、ラベルにするかマルチグルーピングにするか決定しかねてる
- issueをwatchしてみて
bitbucketでgitをサポートし始めた理由は?
- bitbucketを購入した時点では、mercurialだけだったけど、gitのユーザ数が多くなってきたので、自然にサポートしましょうという感じになりました。
co-meeting
吉田パクえさん
co-meeting
- 4人で運営
- life hackerで取り上げられたよ
会議のフロー
パクえ
- ユーザやベンダーが言い難い事を代わりに代弁する。
外部サービスを利用する作戦
できる!Bitbucket Teams
@troterさん
TokyoMercurialを主催
BitBucket歴4年6ヶ月
会社説明
- ToLot
BitBucket Teams
- グループでの作業をサポートする機能
チームにグループを作成
- グループに権限
- 外部公開が簡単
- OSS, 社外の人と連携
- 会社で必要な機能はBitBucket Teamにある
Step by StepでBitbucket Teamの使い方
落穂拾い
質問
- 会社がデカイ場合でも会社名でとったほうが良い?
- 多分取らないほうがよい。プロジェクト名、グループ名から始めてみれば?
- Team account登録時のメールアドレスはどうしたらよい?
- 会社がデカイ場合でも会社名でとったほうが良い?
BitBucketを会社で2年間使って
@methaneさん
Bazaar contributor
- TortoiseBZR
- i18n
Bazaarの良さ
- ファイル名でUnicodeを使用できた
- Bazaar to Git
- Pull Request based workflow
- Github, Bitbucket
- Bitbucketのメリット
- $200/月で使い放題
- admin権とwrite権のようにアクセス権限管理ができた。
- GithubとBitbucketの使い分け
- github
- プロジェクトで使う
- Bitbucket
- 自由なコード置き場
- github
現在の状況
- Github Enterpriseに移行中
BitBucket Pro
会社で使うポイント
- 会社のID管理とできるだけ連携する
- 会社のemailでアカウントを作成してもらう
- 退職時会社のemailで引っ張って削除
- 個人アカウントへのFork対応
- 会社のID管理とできるだけ連携する
Python: Mock
unittestでは基本的にassert等を用いてテストする為,動作の度にランダムに返す値が変わったり,外部サービスと連携するようなメソッドはテストが難しい. Pythonでは,Mockライブラリを使用することで,上記のようなケースでも比較的簡単にテストすることができる.
Mockって?
もしテストしたい対象が内部で下記のようなランダムな値を返す関数を利用している場合,単体テストが非常に面倒臭い.
import random
def randfunc():
return random.randint(0, 10)
randfunc()
# => 0から10の値
def somefunc():
if 5 > randfunc():
return True
else:
return False
# assert ? == somefunc()
# 実行の度にTrueかFalseどちらを返すか分からないので,assertでテストできない.
上記のような場合,ダミーなクラスや関数を作って,置き換えることで,テストがしやすくなる. Mockでは,Mockオブジェクトを作り,置き換えたい関数に代入することで使用する. ダミーの関数の戻り値はreturn_valueで指定できる.
from mock import Mock
randfunc = Mock()
randfunc.return_value = 10
randfunc()
# => 10
# Mockで作ったダミーの関数は常に10を返す.
動的な置き換え
上記ではMockで置き換えた関数はそれ以降ずっとダミーの関数のままになってしまう. Mockでは,patchデコレータやwith構文を使ったコンテキストマネージャーが用意されており,テスト中のみダミー関数に置き換えることができる.
# some.py
class SomeClass(object):
# some process
# 外部サービスと連携するメソッド
def service():
# some process
return "hogehoge"
# tests.py
from mock import patch
#testItの実行中のみダミー関数に置き換わる
#置き換えたいメソッド,ダミーの関数の戻り値をpatchに指定する
@patch("some.SomeClass.service", return_value=100)
def testIt():
import some
result = some.SomeClass.service()
assert result == 100
またwith構文を使った場合は下記のようになる.
def testIt():
# withブロックの間のみダミー関数に置き換わる
with patch("some.SomeClass.service", return_value=100) as m:
import some
result = some.SomeClass.service()
assert result == 100
# 以降は元の関数が使用される
...
その他
Mockライブラリは非常に機能が豊富で,上記のような基本的な使い方以外にも異なった値や例外を返すことができるside_effectや mockが呼び出された回数をチェックできるassert_called_once_with()等色々と便利な機能があるので,少しずつ調べて使っていきたい.
蛇足
「Python プロフェッショナル プログラミング」 でもMockが紹介されているが一部誤植っぽいのを見つけたのでメモ
書籍でのmockのpatchを使ったサンプルコードは下記だが
@patch("myviews.SomeService")
def test_it(MockSomeService):
mock_obj = MockSomeService.return_value
# 再度return_valueが呼ばれている
mock_obj.return_value = 10
# patchではSomeServiceを置き換えているのに,MyViewが呼ばれている
from myviews import MyView
result = Myview()
# 書籍では代入になっていたけど,sphinxで通らない事もあり,正しいと思われる比較に修正
assert result == 10
実際には下記が正しいと思われる.
@patch("myviews.SomeService")
def test_it(MockSomeService):
MockSomeService.return_value = 10
from myviews import SomeService
result = SomeService()
assert result == 10
まぁ,myviews.pyでのMyViewが下記なら元のコードでも問題ないけれど,ちょっとそこまでは読み取れなかった*1.
# myviews.py
def SomeService():
#some process
return "hogehoge"
def MyView():
return SomeService
参考
*1:書かれた当時とmockのversionが変わってる可能性もあるかもしれない.
Django : crash log
DjangoはDEBUGモード(DEBUG=True)では,クラッシュ時にデバッグの為の詳細なスタックトレースをブラウザに表示してくれる. だけど,プロダクション環境でDEBUGモードをFalseに設定した途端,requestの処理中に何か例外が発生し,クラッシュしてもログに何も出力してくれなくなる.さすがにログがないと,何か問題が発生した際に原因を追いようがないので,対処をメモ.
検索するといくつか解決策がでてくるけれど,一番分かりやすかった下記で,今回は対処することにした.
Note that using logging.exception('Some message') with python's standard logging module works just fine in a sginal handler for got_request_exception, if all you are looking to do is log out stack traces. In other words, the traceback is still available in got_request_exception. – TM. Feb 14 '11 at 23:02
python - How do you log server errors on django sites - Stack Overflow
上記を実装したコードが下記になる.signalを使うので,適当なmodels.pyに追加した.
from django.core.signals import got_request_exception
import logging
logger = logging.getLogger("app")
def exception_logging(sender, **kwargs):
logger.exception("[%s]" % kwargs["request"].get_full_path())
got_request_exception.connect(exception_logging)
上で何をしているか簡易に説明すると
django.core.signals.got_request_exception
はrequestの処理中に例外が発生した際に送信され *1,
Logging.exception
はスタックトレースをログに出力する *2 だけなので,上のコードは例外が発生した際のスタックトレースをログに出力していることになる. スタックトレースがそのままログに出力されるので,あまり綺麗とは言えないけれど,当面の目的としては十分なので,今のところは上記で様子を見ようと思う.
本当はDjango側で用意して貰えると,一番なんだけれど.