an odd fellow

仕事のメモ

oracleで今日の日付を取得したり、関数をちょっと試したりする

背景

最近oracleを叩いている。今日の日付を取得する関数が知りたかったので調べた。

結論

select to_char(sysdate, 'yyyy/mm/dd') from dual

で今日の日付が取得できる。to_charの第二引数にフォーマット文字列を渡す。

from dual のdualはダミーテーブルらしい。oracleの全てのユーザーからアクセスできるダミーテーブル。ちょっと関数を試すときなんかは from dual でおk。

locustのNUM_CLIENTSとHATCH_RATEについて

背景

GAEで作ったAPIサーバーを本番反映するに当たり必要なリクエスト数さばけるのかを確認する必要があった。先輩社員がlocustを使っていたので自分もlocustを使ったが、NUM_CLIENTSとHATCH_RATEの挙動が分からな過ぎた。NUM_CLIENTSとHATCH_RATEの関係が分からなかったし、locustを動かしているとAll locusts hatchedというログを残して計測した情報が一旦リセットされる理由もわからなかった。

結論

NUM_CLIENTSは同時接続数でサーバーでさばきたい接続数でOK。

問題はHATCH_RATEでこいつはクライアントを毎秒いくつ作るかを指定する。そしてNUM_CLIENTSで指定した数までクライアントを作ったら統計情報がリセットされる。

つまり最初クライアントは0で、HATCH_RATEで指定した数だけクライアントが作られていくことで、接続数が徐々に増えていく状況をシミュレート出来る。これによりオートスケールの設定が正しく動いているかが確認できる。また、本当に計測したいのは"オートスケールした後のピークリクエスト時に正しくリクエストを捌けるか"なので統計情報がリセットされる。

docker multi stage buildを試す

背景

reviewdogのDockerfileについて先輩社員にレビューもらうと、dockerのmulti stage build使うと幸せになれるよと教えてもらった。

レビューをもらったDockerfileは以下。pythonのdockerイメージにgoをインストールしてからgo getでreviewdogを入れている。これをまずgoのイメージでreviewdogをgo getしてきて、pythonのイメージにコピーしてくればいいんじゃないの?という意図で言ったのだと思う。

FROM python:3.6

USER root
ENV HOME /root

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=${HOME}/go
ENV PATH=${PATH}:/usr/local/go/bin:${GOPATH}/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://github.com/api/v3/"
ARG GITHUB_API_TOKEN=""
ENV REVIEWDOG_GITHUB_API_TOKEN=${GITHUB_API_TOKEN}

# リポジトリをコンテナにマウント
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}
COPY . ${APP_ROOT}

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

結論

やってみた。こんな感じになった。goはバイナリに出来るので、ランタイムが不要になるのでこういうことが出来るのか。素晴らしい。golangのインストールとかGOPATHの設定がなくなっていい感じになりました。

FROM golang:latest as reviewdog
# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog

# ------------------------------------------------------

FROM python:3.6

USER root
ENV HOME /root

# reviewdogの設定
COPY --from=reviewdog /go/bin/reviewdog /usr/local/bin/reviewdog
ENV GITHUB_API="https://github.com/api/v3/"
ARG GITHUB_API_TOKEN=""
ENV REVIEWDOG_GITHUB_API_TOKEN=${GITHUB_API_TOKEN}

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

# リポジトリをコンテナにマウント
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}
COPY . ${APP_ROOT}

# 自前のflake8 pluginのインストール
RUN pip install flake8_ml_batch/

IntelliJでproject painとかをショートカットでリサイズする

背景

IntelliJと書いたがPyCharmもRubyMineでも同様。

Command+1でプロジェクトペインが開けるが、windowをガチャガチャリサイズしたあとだとプロジェクトペインのサイズが以上にデカかったり小さかったりする。マウスでサイズ調整してたが、キーバインド割り当てられてないのか?と思って調べた。

f:id:roronya:20180115134012p:plain

結論

Resize (tool) windows with keyboard | IntelliJ IDEA Blog

リサイズしたいペインにフォーカスを当てて、Shift+Command+カーソルキーでリサイズできた。

docker runでローカルのgoファイルを実行する

背景

RealWorldHTTPを読み始めた。goでサンプルのHTTPサーバを立ててcurlで色々オプションを付けてリクエストを試しながら挙動を確認していくようだった。

それで、サンプルのHTTPサーバーを書いたんだけど、dockerで実行したくて以下のようにした。

$ docker run golang go run server.go

が、当然docker runに渡すコマンドはコンテナ内で実行されるので、server.goはコンテナ内には無いのでこうなる。

stat server.go: no such file or directory

結論

まずdockerコンテナのワーキングディレクトリを調べる。

$ docker run golang pwd
/go

/goらしい

そしたらローカルのカレントディレクトリを/goにボリュームしながらrunする。

$ docker run -v $PWD:/go golang go run server.go

docker run -vに渡すパスは絶対パスでないとならないので.(ドット)で渡すとdockerに怒られるため$PWDとするしかない。

あとはdocker-composeのvolumesを使う方法もあるけど、そのためだけにdocker-compose.ymlを書くのも馬鹿らしいので上でやることにした。

drone.ioでdocker run -vしてハマった

背景

drone.ioでreviewdogを使いたくてこんな感じで書いた。

Dockerfile.reviewdog

FROM python:3.6

USER root
ENV HOME /root
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=$HOME/go
ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://github.com/api/v3/"
ARG GITHUB_API_TOKEN=""
# build時にGITHUB_API_TOKENを渡す
ENV REVIEWDOG_GITHUB_API_TOKEN=$GITHUB_API_TOKEN

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

.drone.yml

pipeline:
  reviewdog:
    image: drone-build:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WORK_DIR=/usr/src/app
    commands:
      - export GITHUB_API_TOKEN="GITHUB_API_TOKEN"
      - docker build --build-arg WORK_DIR=$WORK_DIR --build-arg GITHUB_API_TOKEN=$GITHUB_API_TOKEN -t reviewdog:latest -f Dockerfile.reviewdog .
      - docker run -v $PWD:$WORK_DIR reviewdog:latest /bin/bash -c "flake8 . | reviewdog -ci=droneio -f=pep8"
    when:
      event: pull_request

だが、reviewdogがreviewをしてくれない。(flake8が文句を言うコードはリポジトリに含まれている)

docker run -v $PWD:$WORK_DIR reviewdog:latest /bin/bash -c "flake8 ."

としてもflake8も何も出力してくれなかった。

仮設

docker run -v $PWD:$WORK_DIR reviewdog:latest ls

としたが、droneのログに出力されなかったので、docker run -vが何らかの理由で効いておらずマウントされていないのでないかと考えた。

結論

https://stackoverflow.com/questions/31381322/docker-in-docker-cannot-mount-volume

A Docker container in a Docker container uses the parent HOST's Docker daemon and hence, any volumes that are mounted in the "docker-in-docker" case is still referenced from the HOST, and not from the Container.

Dockerコンテナの中で動かすDockerデーモンはHOSTのものらしい。なので、docker run -v で渡すファイルパスはHOSTのものになってしまっているとのこと。

なので、droneではdocker in dockerは使わないで予めDockerfile.reviewdogの中でCOPYをしてから、prepareでdocker buildするようにしました。

Dockerfile.reviewdog

FROM python:3.6

USER root
ENV HOME /root
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=$HOME/go
ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://github.com/api/v3/"
ARG GITHUB_API_TOKEN=""
# build時にGITHUB_API_TOKENを渡す
ENV REVIEWDOG_GITHUB_API_TOKEN=$GITHUB_API_TOKEN

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

COPY . $APP_ROOT  # ここを追加

.drone.yml

pipeline:
  prepare:  #prepareでdocker buildをしてしまう
    image: drone-build:lates
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WORK_DIR=/usr/src/app
    commands:
      - export GITHUB_API_TOKEN="GITHUB_API_TOKEN"
      - docker build --build-arg WORK_DIR=$WORK_DIR --build-arg GITHUB_API_TOKEN=$GITHUB_API_TOKEN -t reviewdog:latest -f Dockerfile.reviewdog .

  reviewdog:
    image: reviewdog:latest
    environment:
      - flake8 . | reviewdog -ci=droneio -f=pep8
    when:
      event: pull_request

GCPでprojectをまたいだ権限の設定方法

背景

読み飛ばしてOK。自分用メモ。

AppEngineからBigTableを読み込みたかったが、BigTableはprdにあり、AppEngineはdev,stg,prdに立ち上げる予定で、devのAppEngineからprdのBigTableを読み込むとい うprojectを跨いでアクセスする必要があったが、やり方がわからず権限周りに詳しいひとに聞いたので、メモ。

結論

devのAppEngineのサービスアカウントproject-dev@appspot.gserviceaccount.comをprdのIAMから追加しBigTable読み込みの権限を付ける。

サービスアカウントについて

https://cloud.google.com/iam/docs/service-accounts?hl=ja

サービスアカウントについて理解している必要があったので読んだ。

サービスアカウントが良くわからなかったんだけど、公式のマニュアルを読んで理解した。

サービス アカウントは、個々のエンドユーザーではなく、アプリケーションや仮想マシンVM)に属している特別な Google アカウントです。アプリケーションはサ ービス アカウントを使用して、ユーザーの関与を必要とせずに Google のサービス API を呼び出すことができます。

なので、VMを作るとそのVMに対してサービスアカウントが作られて、そのサービスアカウントに設定されている権限の範囲でVMは動作するということだった。

今回の場合はAppEngineのサービスアカウントに対して、BigTableの読み込み権限を付けることで、AppEngineはBigTableを読み込むことができるようになる。