oinume journal

Scratchpad of what I learned

AnsibleでPlaybook流した時のgit commit hashをファイルに出力したら捗った

「このサーバにどこまでPlaybook流したんだっけ?」みたいなことでよく悩んでいたので、AnsibleのPlaybookが入ったリポジトリのgit commit hashをファイルに出力してそれをサーバーに置くようにしてみた。

こんな感じのアクションをPlaybookに書いて簡単にできた。

- local_action: shell /usr/bin/git show -s --format=%H > /tmp/version.txt
  sudo: False
- copy: src=/tmp/version.txt dest=/var/tmp/version.txt

入門Ansible

入門Ansible

新年の抱負の進捗どうですか?

oinume.hatenablog.com

こんな感じの新年の抱負を書いたのだけど、そろそろ2015年も40%経過したので進捗報告。

Dockerを実戦投入する

進捗ダメです。やっと個人でDockerを使い始めたレベル。

英語でブログエントリーを書く割合を25%にしてみる

この2つは英語でかいて、あとひとつは日本語なので今のところ達成!しかしそもそも激烈にブログ頻度が低下しているのでそっちの方がやばい。

フロントエンド(Web)を頑張る

これは個人的なキャリアの方向転換により諦めました()

Reactive Programmingをちゃんと理解する

これも個人的なキャリアの(ry

アルゴリズムを深く理解する

進捗ダメです... インプットはしてるけどアウトプットをしていないので完全に身になってない。

方向転換

やっぱり自分はサーバサイドエンジニアとして頑張っていこうと思ったので、今後は機械学習とか自然言語処理を頑張っていく所存です。

開発スピードと技術的負債

よくある「開発スピードを優先させるか技術的負債をなるべく発生させないようにするか」という議論、ケースバイケースだとは思うけど、ことプロダクトの立ち上げ段階では、悩んだら「開発スピード」を優先させるようにするべきだと自分は思ってる。

理由は 市場は待ってくれないから。どんなにいいプロダクトでもユーザーに使われなくては意味がないのと、プロダクトを取り巻く外部の環境(競合プロダクトや市場でのニーズ)は自分ではコントロールできないものなのに対して、技術的負債については適切に管理されていればコントロールしながら返済できるから。もちろんバランスも重要だとは思うので、どんな技術的負債も生み出していいかと言われるとそうではないけど。

というわけで自分は「ああこれクソコードだけど機能は満たしてるからそのままリリースしたいなぁ」というのはだいたいクソコードのままリリースしています。(こうやって免罪符を作っているのです)

Mocking a HTTP access with http.Transport in Golang

I've investegated a way to mock HTTP request and response when writing a code to access to a HTTP API with http.Client. Finally, I found that I can do it by just implementing RoundTrip method of http.RoundTripper.

Here is an example of mocking and proxying HTTP request and response. Running with go run main.go -mock mock, you can get mocked result and with go run main.go -mock proxy, you can get proxied result with httptest.Server.

package main

import (
    "flag"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/http/httptest"
    "net/url"
    "strings"
)

var mock = flag.String("mock", "", "Doesn't perform real access when 'proxy' or 'mock' is specified")

func main() {
    flag.Parse()
    client := http.DefaultClient

    if *mock == "proxy" {
        server := newServer()
        defer server.Close()

        client.Transport = &http.Transport{
            // Proxy to httptest.Server which created above
            Proxy: func(req *http.Request) (*url.URL, error) {
                return url.Parse(server.URL)
            },
        }
    } else if *mock == "mock" {
        client.Transport = newMockTransport()
    }

    resp, err := client.Get("http://ifconfig.co/all.json")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println("GET http://ifconfig.co/all.json")
    fmt.Println(string(body))
}

// Create a HTTP server to return mocked response
func newServer() *httptest.Server {
    return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(200)
        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintln(w,
            `{
    "Accept-Encoding": [
        "proxy"
    ],
    "User-Agent": [
        "proxy"
    ],
    "X-Ip-Country": [
        "Japan(Proxy)"
    ],
    "X-Real-Ip": [
        "192.168.1.1"
    ]
}`)
    }))
}

type mockTransport struct{}

func newMockTransport() http.RoundTripper {
    return &mockTransport{}
}

// Implement http.RoundTripper
func (t *mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    // Create mocked http.Response
    response := &http.Response{
        Header:     make(http.Header),
        Request:    req,
        StatusCode: http.StatusOK,
    }
    response.Header.Set("Content-Type", "application/json")

    responseBody :=
        `{
    "Accept-Encoding": [
        "mock"
    ],
    "User-Agent": [
        "mock"
    ],
    "X-Ip-Country": [
        "Japan(Mock)"
    ],
    "X-Real-Ip": [
        "192.168.1.1"
    ]
}`
    response.Body = ioutil.NopCloser(strings.NewReader(responseBody))
    return response, nil
}

I think it's very simple to mock a HTTP request in GoLang. net/http package is awesome.

Go Programming Blueprints

Go Programming Blueprints

Changing bower package cache directory

bower caches packages in ~/.cache/bower. How can I change the directory? bower's document says "Add the following in .bowerrc" but it's totally wrong.

"storage": {
  "cache" : "~/.bower/cache",
  "registry" : "~/.bower/registry"
}

I try the configuration and run bower install but nothing changed. I finally found out correct configuration in bower/config repo.

"storage": {
  packages: ".bower/packages",
  registry: ".bower/registry"
}

Why the document of famous software such as bower is wrong?

TypeScript Essentials

TypeScript Essentials