httptestでWriteHeaderができなかった話
はじめに goでhttpのhandlerのテストを書いているときに詰まったところを書きます。 詰まったところは、httptest.NewRecoder()の再利用ができなかったことです。 正確には、再利用する方法はあるかもしれないがよくわからなかったので、再度NewRecoder()を呼び出して、新規作成した、で解決しました。
内容
package mytest import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" ) func TestOverride(t *testing.T) { handler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { var js map[string]interface{} decoder := json.NewDecoder(req.Body) if err := decoder.Decode(&js); err == nil { if js["msg"] == "error" { res.WriteHeader(http.StatusBadRequest) res.Write([]byte(`{"result": false}`)) } else { res.WriteHeader(http.StatusOK) res.Write([]byte(`{"result": true}`)) } } }) // 1: StatusOK jsons := `{"msg": "test"}` w := httptest.NewRecorder() r, err := newRequest([]byte(jsons), "POST", "application/json") if err != nil { t.Errorf("%s", err) } handler.ServeHTTP(w, r) if w.Code != http.StatusOK { t.Errorf("Expected status code is 200 but got %d", w.Code) } // 2: BadRequest error code jsons = `{"msg": "error"}` w = httptest.NewRecorder() // ここで再度NewRecoder()を呼ぶ r, err = newRequest([]byte(jsons), "POST", "application/json") if err != nil { t.Errorf("%s", err) } handler.ServeHTTP(w, r) if w.Code == http.StatusOK { t.Errorf("Expected status code is NOT 200 but got %d", w.Code) } } func newRequest(data []byte, method string, c string) (*http.Request, error) { req, err := http.NewRequest( method, "", bytes.NewBuffer([]byte(data)), ) req.Header.Set("Content-Type", c) return req, err }
上記は、テストが通ります。
はじめは、コメント部分をw.Body.Reset()をすれば大丈夫なのかなぁと安易にやったのですが、そうするとHeader部分への上書きはできませんでした。おそらく、GOの公式ドキュメントに記載されている内容なのかと思います。したがって、w.Body.Reset()で行うと、2回目のBadRequestのエラーを期待するのですが200が返ってくる結果となってしまいます。
goのバージョンを切り替えるだけのスクリプトコマンドを作成
はじめに
goのバージョンだけを単に切り替えたかったので、goのバージョンを切り替えるだけのスクリプトコマンドを作りました。 自分用でサクッと作ったため、installのファイルはlinux-amd64のみ対象としちゃってます。
インストール
ソースをダウンロードして、パスが通った場所にファイルを置くだけです。
$ git clone https://github.com/tkyshm/goenv.git $ mv bin/goenv /usr/local/bin
また、bash、zshの補完が使いたい場合は、補完関数も用意したのでcompletionsが格納されたディレクトリに放り投げるか読み込んであげれば補完もできるようになります。
使い方
helpを使っていただければほとんどわかるかと思います(中身単純なので)。
$ goenv help
切り替えはuseのsubcommandを使えばできます。 下みたいな感じです。
$ goenv use go1.6rc2 switched go version. go version go1.6rc2 linux/amd64
Chefで複数リソースに更新があった時だけbashを実行
はじめに
cookbookのfilesの中に大量のtomlファイルが入っていて、各tomlファイルに対してコマンドを実行したい場面に直面しました。 ファイルの更新が合った時だけ、そのコマンドを実行したかったので、その時の作業をメモします。
目的
- confファイルが更新されているかをチェック
- 更新されていればファイルを差し替えしてスクリプトを実行
作業
作業環境は、仮想マシンにChef-ServerとChef-Clientを用意し、作業(knifeを実行するマシン)はホストマシンになります。 下記、レシピになります。
recipe.rb
files = run_context.cookbook_collection["my-cookbook-name"].file_filenames files.select!{ |file| file =~ /\.toml/ } files.each do |file| # 2. 配置したtomlを使ってコマンドを実行 bash "exec-#{File.basename(file,".*")}" do action :nothing # 実行しない user "vagrant" cwd "/home/vagrant/conf" code "echo #{File.basename(file,".*")} >> /home/vagrant/exec-stamp.txt" # 処理したいコマンド end end files.each do |file| # 1. tomlを配置 cookbook_file "/home/vagrant/conf/#{File.basename(file)}" do owner "vagrant" group "vagrant" mode 0644 source File.basename file not_if { FileUtils.cmp("/home/vagrant/conf/#{File.basename(file)}", file) } # ファイルの比較 notifies :run, "bash[exec-#{File.basename(file,".*")}]" # bash[exec-hoge] の内容を実行しにいく end end続きを読む
レキシカルスコープとダイナミックスコープ
はじめに
レキシカルスコープとダイナミックスコープの違いについて簡単にまとめてみます。
メモ
以下、サンプルコードを元にして説明していきます。
1: func X(){ 2: print(s) 3: } 4: 5: func Y() int{ 6: s := 12 7: X() 8: return s 9: }
上記のコードで想定している出力結果は、関数Yを呼び出したら12が出力されることとします。 実行している内容は、関数Yで定義された変数sを関数Xで出力するというものです。 下記、2つにスコープに分けて説明します。
続きを読むDockerでoperation not supportedが出てきた話
はじめに
DockerでイメージをbuildしようとDockerfileの作ってbuildしてみたものの、
operation not supported
というメッセージでRUNで記載したコマンドが実行できない事象に陥りました。
解決方法
LXCを導入したい場合、以下必要なことがわかりました(根本的な理由は調べてません)。
- CONFIG_VETHの値(カーネルコンフィグ)
- lxc
- cgroups
CONFIG_VETHの値の確認は下記コマンドにて行いました。 下記の結果が表示されていれば値が入っている状態となります。
$ zcat /proc/config.gz | grep VETH CONFIG_VETH=m
ちなみに、上記表記が出ない場合の対策については実施していません。
cgroupsはubuntuなどのOSであれば、cgroup-liteをapt-getしてあげるらしいです。 Archlinuxの環境ではyaourt -S libcgroupsが必要でした。下記のコマンドは適宜読み替えてください。
$ yaourt -S libcgroups $ sudo pacman -S lxc
dockerでbuildとりあえずうまく行きました。。。
続きを読むRiak searchを使ってみた
はじめに
Riakで全文検索してみたいと思い、Riakのsearch機能を利用する準備で行った作業をまとめました。
利用環境
- Ubuntu server 14.04
- Riakのホストは192.168.56.101
- Riak 2.0.5(from source)
前準備
- ビルドしたriakの設定ファイルetc/riak.confの"search = off"を"search = on"に書き換える
- basho/riak-erlang-client · GitHub
作業
indexの作成
例として、"api_index"という名前のindexを作成します。
export RIAK_HOST="http://192.168.56.101:8098" curl -XPUT $RIAK_HOST/search/index/api_index \ -H 'Content-Type: application/json' \ -d '{"schema":"_yz_default"}'
下記、URLにアクセスし、api_indexのsolrのcore(?)が作成されているか確認します。 ※ solrについて詳しくないので上記言い回し的に間違ってたらご指摘ください。
http://192.168.56.101:8093/internal_solr/
続きを読むCowboyでobserverを起動するメモ
目的
軽量HTTPサーバcowboyのアプリケーションをErlangの監視ツールobserverで視覚的に監視できるようにしたい。
実施内容
- relx.configの編集
レシピ
relx.configの作成したアプリケーション名(以下app_name)の他に、
- wx
- observer
- runtime_tools
の3つを追加します。
{release, {animeeting_release, "1"}, [app_name,wx,observer,runtime_tools]}. --省略--
上記の対処でobserverが起動できるようになります。 アプリをconsoleで起動し、下記コマンドをerlシェルで実行します。
1> observer:start().
下図みたいな感じなものが見れるようになります。
続きを読む