mind.

学んだことの記録

Rails + PostgreSQLでカラムをキャストできない型に変更する方法

トラブル時の状況

  • bit_varying型のカラムをinteger型に変更したかったがCAST()で雑にキャストできなかった
  • 一旦string型に変更してからinteger型に変更しようとするマイグレーションを実行したが、string型で処理されてしまった

解決方法

カラムを削除する変更と追加する変更を行う
マイグレーションファイル

class ChangeUserHogehogeToInteger < ActiveRecord::Migration[5.2]
  def change
    remove_column :user, :hogehoge
    add_column :user, :hogehoge, :integer, null: false, comment: "hoge"
  end
end

カラムの変更後に必要な作業

  • モデルテストの修正
  • モデルのバリデーション修正

おまけ

  • integerに変更後、負数を許さない場合はモデルでバリデーションチェックを行う
  validates :hogehoge, presence: true, numericality: { greater_than_or_equal_to: 0 }

参考

qiita.com

この記事はkb Advent Calendar 2020 3日目の記事です。

adventar.org

『SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップ』を読んで

感想

スクラムマスターのあるべき精神が完結にまとめられた本です。
ページ数もそれほど多くなく、説明も端的でわかりやすいので読みやすかったです。

こんな人におすすめ

スクラムガイドを読んでスクラムの概要は理解できたものの、スクラムマスターとしてどう振る舞えばいいのかわからない人。

以下、印象に残った部分

心理状態モデル

全部なるはやで問題解決してチームを作業に戻したい衝動に抵抗できれば、「自己組織化したチームを作る」という目標に大きく近づきます。

僕が初めてスクラムマスターをやったとき、問題が発生するとすぐに割って入って答えを言っていました。
やがて、チームが次に何か問題に直面したとき、僕の指示を仰ぐようになりました。良くないことだったと反省しています。

たとえ最強のアジャイルコーチでも、1人で組織を変えることはできません。成功には、自己組織化したチームが必要です。ですから、スクラムマスターたちで構成されるチームを作るのが最良の出発点になります。

スクラムをやろうとしても経営に近いところにいる役職者の理解を得ることが難しいと日頃感じています。
たとえ正しいことでも1人でプレゼンなどの啓蒙活動をしていても、正論を押し付けるだけのようになってしまい、あまりいい反応が得られませんでした。
そのような状況でも志を共にする仲間がいれば力強いですね。

インパクマッピング

システム全体を俯瞰する。細かいプロセスにはこだわらずに何が課題かを考える。

コミットメントに苦労しているというチームをよく見かけますが、解決すべき課題はより低レベルの信頼の欠如にあるものです。

仕事では、KPTをやっているものの、あまり深堀りせずTryを考えようとするのでいつも対処療法になります。
議論を深めて根本原因を取り除こうとせず、議論を避けて無駄な作業を減らそうとしない雰囲気がチームを取り巻いているように感じています。

中には、チームにとって受け入れるのが簡単ではないプラクティスもありました。スタンドアップミーティングなどです。そのため、回数を減らすか、全部やめようとしています。

耳が痛いです…。プロダクトバックログリファインメントはちょくちょくスキップされます。
守破離の「守」でスクラムを体に染み込ませないまま、型を崩してはいけませんよね。

まとめ

内容は認定スクラムマスター(CSM)研修で学んだことと齟齬は無く、翻訳も丁寧で読みやすかったです。
読んで満足するのではなく、カイゼンに繋がるような動きができるよう、頑張らなくてはならないですね。

SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップ

Railsチュートリアルで作成したサンプルアプリをDockerで動かす手順

雑に備忘録

基本的な内容は下記ページに書かれているもので、それをRailsチュートリアルで作成したサンプルアプリ向けにまとめました。
docs.docker.com ローカルPCで動かす想定です。

以下、コマンドとファイルの記載内容

nano Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /sample-app
WORKDIR /sample-app
COPY Gemfile /sample-app/Gemfile
COPY Gemfile.lock /sample-app/Gemfile.lock
RUN bundle install
COPY . /sample-app

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

※Dockerサイトのテンプレートから「Myapp」を「sample-app」に置き換えています。

nano Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'
touch Gemfile.lock
nano entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
nano docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/sample-app
    ports:
      - "3000:3000"
    depends_on:
      - db

※Dockerサイトのテンプレートから「Myapp」を「sample-app」に置き換えています。

リポジトリのクローン

git clone [リポジトリのURL]

リポジトリのファイルを移動

cd sample_app
mv * ../
mv .git ../
mv .gitignore ../
cd ..
rm -rf sample_app

イメージ作成

docker-compose build

データベース作成

docker-compose run web rake db:create

データベースのマイグレーション

docker-compose run web rake db:migrate

サンプルデータの反映

docker-compose run web rake db:seed

アプリケーションのコンテナ起動

docker-compose up

完了

余談

Postgresqlのコンテナ起動してもRails側でDBの設定変えないとデフォルトのSQLite使っちゃいます。
Dockerfile、docker-compose.yml、entrypoint.sh、Gemfile.lockはリポジトリに入れておくと便利です。

AWSでEC2インスタンスを最小構成で作成する手順

最小構成でWebサーバー用のEC2インスタンスを立ち上げる手順をメモしておきます。
後述する書籍の内容を参考に、チェックシート的な使い方ができるようにしました。

目標

VPC、サブネット、EC2インスタンスそれぞれ一つずつ作成し、EC2インスタンスSSHでログインする。

手順

  1. VPCを作成する
    「名前タグ」は自由、「IPv4 CIDR ブロック」は「10.0.0.0/16」
  2. サブネットを作成する
    「名前タグ」は自由、「VPC」は1で作成したもの、「アベイラビリティーゾーン」は自由、「IPv4 CIDR ブロック」は「10.0.1.0/24」
  3. インターネットゲートウェイを作成する
    「名前タグ」は自由
  4. インターネットゲートウェイVPCにアタッチする
    3で作成したインターネットゲートウェイを選択した状態で、「アクション」→「VPCにアタッチ」→「使用可能な VPC」に1で作成したVPCを選択して「インターネットゲートウェイのアタッチ」
  5. ルートテーブルを作成
    「名前タグ」は自由、「VPC」は1で作成したもの
  6. ルートテーブルにサブネットを関連付ける
    5で作成したルートテーブルを選択して、画面中央部にある「サブネットの関連付け」タブを選択した状態で「サブネットの関連付けの編集」
    2で作成したサブネットがリストに表示されていることを確認して選択し「保存」
  7. ルートテーブルにインターネットゲートウェイのルートを追加する
    5で作成したルートテーブルを選択して、画面中央部にある「ルート」タブを選択した状態で「ルートの編集」
    送信先」は「0.0.0.0/0」、ターゲットは3で作成したインターネットゲートウェイを選択
  8. EC2インスタンスの作成
    「ネットワーク」は1で作成したVPC、「サブネット」は2で作成したもの、「自動割り当てパブリック IP」は「サブネット設定を使用(有効)」を選択
    「ネットワークインターフェース」の「プライマリIP」に「10.0.1.10」を入力
    「セキュリティグループの設定」で「新しいセキュリティグループを作成する」を選択、「SSH」(初期状態で設定済み)と「HTTP」のようなWebアプリへアクセスするためのルールを設定
    他の項目は自由
    秘密鍵を忘れずにダウンロードする
  9. ローカルPCからSSHログインできるか確認する
ssh -i [秘密鍵のパス] ec2-user@[EC2インスタンスのIPアドレス]

参考書籍

丁寧な説明で分かりやすくおすすめです。

余談

「6.ルートテーブルにサブネットを関連付ける」を忘れがち

GitLabをhttpsでアクセスするように設定した後はGitLab APIのオプションにverifyを追加する

仕事で使っているGitLabをhttpsに設定したときにバックアップに使っているスクリプトを変更し忘れたので自戒を込めて書きます。

Pythonで確認

元にしたコードは下記の以前書いた記事に記載しています。
learning-mind.hatenablog.com

def get_all_user_email_dict():
    headers = {
        'Private-Token': os.environ['ACCESS_TOKEN'],
    }
    params = (
        ('page', '1'),
        ('per_page', '1000'),
    )

    response = requests.get('https://XXXXX/api/v4/users', headers=headers, params=params, verify="ca.crt")
    data = response.json()
    path_dict = dict()
    for row in data:
        username = json.dumps(row["username"], indent=4).replace("\"", "")
        path_dict[username] = json.dumps(row["email"], indent=4).replace("\"", "")

    return path_dict

下記の部分を修正しました。

    response = requests.get('https://XXXXX/api/v4/users', headers=headers, params=params, verify="ca.crt")

verify="ca.crt""ca.crt"はクライアント証明書のファイル名です。
verifyのパラメータはFalseでも処理は進みますが、警告が表示されます。

コマンドで確認

元にしたコマンドは↓ learning-mind.hatenablog.com

curl --cacert ca.crt --header "Private-Token: $ACCESS_TOKEN" https://XXXXX/api/v4/users | jq .projects[].path

URLおよびファイル名は環境に合わせてください。
--cacert ca.crtが追加されています。
--cacertcurlのオプションで、ca.crtはクライアント証明書のファイル名です。

感想

自分が書いた記事に助けられることは多い

『アマゾンのすごいルール』を読んで

どのような本か

アマゾンで敷かれているルールについて、著者である佐藤将之さんがアマゾン社員時代に経験したこと踏まえて説明されている本です。
内容は、2018年に出版されたということもあり、紹介されているルールはネットニュースでの話題になったことも多く、目新しいことは多くはありませんでした。 ただ、著者の経験したことは読んでいて状況がイメージしやすく、アマゾンのルールの本質を理解できました。

印象に残った箇所

AWSのサービス開始に至った経緯

アメリカの人たちはクリスマスに集中してものを買うそうです。
クリスマス商戦の商品を補充しておくための大規模な倉庫を保有しているのですが、クリスマス以外の時期は他の業者に貸しています。
それと同様の発想で、クリスマス時期の大量アクセスに耐えきる程のサーバーを閑散期に貸し出すAWSが生まれたそうです。
AWSを知ったときは「先見の明があるなあ」くらいにしか思っていませんでしたが、倉庫の例を知ることで、AWSは生まれるべくして生まれたと思えました。

「在庫なし」の商品ページへのアクセス数をチェックしている

アマゾンはロングテール戦略をとっていて、めったに売れない商品、所謂「死に筋商品」も商品が無くならない限り商品ページを載せ続けます。
その戦略をとるに至ったのは、「在庫なし」の商品ページへのアクセス数をチェックしていたからということでした。
欲しい商品の在庫が無い状態が続いているなら何回もアクセスしてみるといいかもしれませんね。(笑)

移動サーバールーム

ある時、大企業のデータをAWSに移行するとき、遅い転送速度をフォローするために、トラックに積んだサーバーに太い光ファイバーを使ってデータを移して運んだそうです。
これはアマゾンがスピードを重視しているという方針から行ったそうです。
ドラマ『シリコンバレー』でも、経緯は全く違いますがサーバーをトラックで運ぶというエピソードがありましたね。
もしかしたらアマゾンのエピソードが元ネタになっているのかも知れません。

全体的に、読んでいると著者のアマゾンに対する強い愛が伝わってくる文章でした。

PCの再起動時にplymouthが止まってGitLabが起動しなかった件

困った……

仕事で使っているGitLabのサーバーPCを再起動した後、いつも通りブラウザでページを開こうとするとエラー画面が表示されました。
サーバーにSSHで入って状態を見ると、GitLabとそれに関わるプロセスが起動していませんでした。
設定は、システム起動時に自動的に起動するようにしていたにも関わらず起動できないとはむむむ……。

とりあえずGitLabの起動コマンドを打ってみたものの失敗しました。

gitlab-ctl start

下記記事と現象は同じでした。
writesnow.net

$ sudo gitlab-ctl start
fail: alertmanager: runsv not running
fail: gitaly: runsv not running
fail: gitlab-monitor: runsv not running
fail: gitlab-workhorse: runsv not running
fail: logrotate: runsv not running
fail: nginx: runsv not running
fail: node-exporter: runsv not running
fail: postgres-exporter: runsv not running
fail: postgresql: runsv not running
fail: prometheus: runsv not running
fail: redis: runsv not running
fail: redis-exporter: runsv not running
fail: registry: runsv not running
fail: sidekiq: runsv not running
fail: unicorn: runsv not running

上記ページには解決策も書かれていますが、僕の環境では下記コマンドを実行しても反応が無いという状況でした。

systemctl start gitlab-runsvdir

その他、Rubyのバージョンを確認したりもしましたが、僕が使っていたGitLabはOmnibus packageでインストールしたので関係ありませんでした。

結論

plymouth-quit-waitが動き続けていたため他のプロセスが起動できなかったことが原因でした。
(GitLab依存の問題ではありませんでしたので、影響は他のアプリにもあったかもしれません)

原因の特定に至った過程

この現象についてGitLabの公式ページに書かれていました。

docs.gitlab.com

Since GitLab 11.2, the gitlab-runsvdir starts during the multi-user.target instead of basic.target. If you are having trouble starting this service after upgrading GitLab, you may need to check that your system has properly booted all the required services for multi-user.target via the command:

つまり、誰かがGitLabに必要なサービスの起動を妨げているようです。
公式ページに従って、妨げているサービスを確認します。

systemctl -t target

このとき、loaded inactive deadとなっているサービスが二つありました。
(抜粋)

graphical.target       loaded inactive dead   start Graphical Interface
multi-user.target      loaded inactive dead   start Multi-User System

この二つが原因のようです。
前述の公式ページに書かれている通り、次のコマンドでsystemdのキューを確認します。

systemctl list-jobs

結果(抜粋)

plymouth-quit-wait.service           start running

plymouth-quit-waitrunningのまま止まっていました。

plymouthとは

plymouthはシステム起動時および終了時のスプラッシュを表示するソフトだそうです。

access.redhat.com

調べると、下記ページのようにアンインストールすることで解決できると書かれていました。

www.hiroom2.com

しかし、業務で使用しているということもあり極力既存のモジュールをアンインストールしたくはありませんでした。

解決策

GUIモードで起動しようとして止まっているので、CUIモードに切り替えると解決しました。

systemctl isolate multi-user.target

access.redhat.com

念のためキューを確認します。

# systemctl list-jobs
No jobs running.

# systemctl -t targetを実行するとrunningのままのサービスはありませんでした。

感想

正直危なかった……。先輩に教えてもらえなかったら解決できてなかったかもしれません。感謝です。
そろそろLPICとか取った方がいいのかとも思いました。