2020年4月25日土曜日

Rails.cache を使って SQL クエリの結果をキャッシュしてみた

概要

前回 Postgres を使って Rails6 に入門しました
今回はそのアプリを使って Rails のクエリキャッシュ機能を使ってみたいと思います
簡単に言えば同じクエリは毎回データベースに問い合わせせずにメモリや Redis にキャッシュするという機能です
Rails のバージョンによって構文や使い方が異なるので注意してください

環境

  • macOS 10.15.4
  • Rails 6.0.2.2
  • Redis 5.0.5

キャッシュの有効化

  • rails dev:cache

キャッシュするクエリをモデルで定義する

  • vim app/models/my_task.rb
class MyTask < ApplicationRecord
  def self.cache_all
    Rails.cache.fetch("#{cache_versioning}/list", expires_in: 30.seconds) do
      MyTask.order(posted_date: "DESC").all.to_a
    end
  end
end

ポイントは最後に to_a を付けて配列として返している点です

コントローラでキャッシュを参照するメソッドを使う

  • vim app/controllers/my_tasks_controller.rb
class MyTasksController < ApplicationController
  protect_from_forgery

  def list
    @my_tasks = MyTask.cache_all
  end

  # 一部省略・・・
end

動作確認

  • rails s

で起動して localhost:3000/my_tasks にアクセスしてみましょう

  • c=0 && while :;do ((c ++)); echo $c; curl localhost:3000/my_tasks > /dev/null 2>&1; sleep 1; done

紹介のアクセスは SQL が発行されていますが 2 回目以降は 30 秒経過するまでは SQL が発行されていないのがログから確認できると思います

おまけ: redis をキャッシュにする方法

上記はメモリ上にキャッシュを持っており参照するのが大変です
そんな場合は redis を使いましょう

redis のインストール

  • vim Gemfile
gem "redis_rails"
  • bundle install

config.cache_store の変更

設定ファイルを変更してオンメモリだったキャッシュ先を redis に変更します
Rails6 では :redis_cache_store, { url: ENV['REDIS_URL'] }

  • vim config/environments/development.rb
    (一部省略)
if Rails.root.join('tmp', 'caching-dev.txt').exist?
  config.action_controller.perform_caching = true
  config.action_controller.enable_fragment_cache_logging = true

  # config.cache_store = :memory_store
  config.cache_store = :redis_cache_store, { url: "redis://192.168.100.1/0" }
  config.public_file_server.headers = {
    'Cache-Control' => "public, max-age=#{2.days.to_i}"
  }
else
  config.action_controller.perform_caching = false

  config.cache_store = :null_store
end

あとは redis を起動してアプリで確認すればキャッシュが redis に作成されていることが確認できると思います

192.168.100.1:6379> keys *
1) "true/list"
192.168.100.1:6379> TTL true/list
(integer) 19

データ自体は圧縮されていて平文では確認が難しい状態になっています
redis のエンドポイントに関する細かい設定は参考サイトにあるドキュメントを確認してください

最後に

Rails6 で Rails.cache を使ってみました
かなり簡単に使えました
リアルタイムでの表示が不要であったりデータがすぐに反映されなくても良いようなビューを扱う場合はかなり使える技だと思います

今回は SQL 文の発行をキャッシュしましたがビューの情報やネスト構造の一部だけをキャッシュするロシアンドールキャッシングなどもありいろいろな情報をキャッシュすることができます

参考サイト

2020年4月24日金曜日

Gitlab 11.8 をソースコードからインストールしてみた

概要

Gitlab をソースコードからインストールしてみました
基本は公式のドキュメントを参考にしています
バージョンも上記のドキュメントに記載の通り 11.8 というバージョンをインストールしています 

Gitlab 自体の開発をしたりビルドする必要がある場合には必須かなと思います
Ruby のバージョンは公式のドキュメントだと 2.6 ですが 2.6 だと protocolbuf などがインストールできないので 2.5.3 を使います

環境

ビルドが成功した際の各種パッケージや言語環境のバージョンは以下の通りです

  • Gitlab
  • Ubuntu 16.04.6 LTS
  • Ruby 2.5.3 (rvm)
  • Go 1.13.5
  • Nodejs 12.16.2
    • yarn 1.22.4
  • Postgres 9.5.21
  • Redis 3.0.6
  • git 2.26.2

依存パッケージのインストール

  • sudo su -
  • apt -y update
apt -y install build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev \
  libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev \
  libxslt-dev libcurl4-openssl-dev libicu-dev logrotate rsync python-docutils pkg-config cmake \
  runit

editor コマンドのエディタを vim にする

  • sudo su -
  • update-alternatives --set editor /usr/bin/vim.basic

git の最新版をインストール

2.18 以上のバージョンが必要なためです
Ubuntu16.04 のデフォルトリポジトリだと古い git がインストールされてしまいます

  • sudo su -
  • add-apt-repository ppa:git-core/ppa
  • apt -y update
  • apt -y install git

Ruby のインストール

rvm から 2.5.3 をインストールします

  • sudo apt -y install gnupg2
  • gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
  • \curl -sSL https://get.rvm.io | bash -s stable
  • /usr/local/rvm/bin/rvm install ruby-2.5.3
  • /usr/local/rvm/bin/rvm alias create default ruby-2.5.3

ruby -v でバージョンが表示されれば OK です

Go のインストール

  • sudo su -
  • mkdir /tmp/go && cd /tmp/go
  • curl --remote-name --progress https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz
  • echo '512103d7ad296467814a6e3f635631bd35574cab3369a97a323c9a585ccaa569 go1.13.5.linux-amd64.tar.gz' | shasum -a256 -c - && tar -C /usr/local -xzf go1.13.5.linux-amd64.tar.gz
  • ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/

go version でバージョンが表示されれば OK です

Nodejs と yarn のインストール

  • sudo su -
  • curl --location https://deb.nodesource.com/setup_12.x | bash -
  • apt -y install nodejs
  • curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
  • echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
  • apt -y update
  • apt -y install yarn

node -vyarn -v でバージョンが表示されれば OK です

git ユーザの作成

git ユーザは Gitlab のアプリケーションの所有者になります

  • sudo su -
  • adduser --disabled-login --gecos 'GitLab' git

Postgres のインストールと設定

  • sudo su -
  • apt -y install postgresql postgresql-client libpq-dev postgresql-contrib

続いてデータベースの作成などを行います
公式の手順にはない手順として git ロールのパスワードの設定をしています
このパスワードはデフォルトの database.yml に記載されているパスワードになります

  • systemctl start postgresql
  • su - postgres
  • sudo -u postgres psql -d template1 -c "CREATE USER git CREATEDB;"
  • sudo -u postgres psql -d template1 -c "ALTER ROLE git WITH PASSWORD 'secure password';"
  • sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
  • sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;"
  • `sudo -u git -H psql -d gitlabhq_production

SQL プロンプトになったら pg_trgm エクステンションが有効になっているか確認します

  • SELECT true AS enabled FROM pg_available_extensions WHERE name = 'pg_trgm' AND installed_version IS NOT NULL;

Redis のインストール

  • sudo su -
  • apt -y install redis-server

設定ファイルを編集して socket ファイルでローカル接続できるようにします
オリジナルのファイルの一部を書き換えて書き換えた設定を新たなコンフィグファイルとして書き換えています
また tmp ディレクトリを定期的に削除するルールを追加します

  • cp /etc/redis/redis.conf /etc/redis/redis.conf.orig
  • sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | tee /etc/redis/redis.conf
  • echo 'unixsocket /var/run/redis/redis.sock' | tee -a /etc/redis/redis.conf
  • echo 'unixsocketperm 770' | tee -a /etc/redis/redis.conf
  • mkdir -p /var/run/redis
  • chown redis:redis /var/run/redis
  • chmod 755 /var/run/redis
if [ -d /etc/tmpfiles.d ]; then
  echo 'd  /var/run/redis  0755  redis  redis  10d  -' | tee -a /etc/tmpfiles.d/redis.conf
fi
  • systemctl restart redis
  • usermod -aG redis git

redis-cli -s /var/run/redis/redis.sock で接続できれば OK です

Gitlab インストールと設定

  • sudo su -
  • cd /home/git
  • git config --global http.postBuffer 524288000
  • sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-foss.git -b 11-8-stable gitlab

リポジトリがかなり大きいです
error: RPC failed; curl 56 LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54 などが出る場合は以下の shallow clone を試してみてください

  • sudo -u git -H git clone --depth 1 https://gitlab.com/gitlab-org/gitlab-foss.git -b 11-8-stable gitlab

必要な設定ファイルの配置を行います
シングルホストであれば基本はデフォルトのままで動作するはずです

  • cd /home/git/gitlab
  • sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
  • # sudo -u git -H editor config/gitlab.yml
  • sudo -u git -H cp config/secrets.yml.example config/secrets.yml
  • sudo -u git -H chmod 0600 config/secrets.yml
  • sudo chown -R git log/
  • sudo chown -R git tmp/
  • sudo chmod -R u+rwX,go-w log/
  • sudo chmod -R u+rwX tmp/
  • sudo chmod -R u+rwX tmp/pids/
  • sudo chmod -R u+rwX tmp/sockets/
  • sudo -u git -H mkdir -p public/uploads/
  • sudo chmod 0700 public/uploads
  • sudo chmod -R u+rwX builds/
  • sudo chmod -R u+rwX shared/artifacts/
  • sudo chmod -R ug+rwX shared/pages/
  • # sudo -u git -H cp config/puma.example.development.rb config/puma.rb
  • # sudo -u git -H editor config/puma.rb
  • sudo -u git -H cp config/unicorn.rb.example.development config/unicorn.rb
  • sudo -u git -H editor config/unicorn.rb
#listen '/home/git/gitlab.socket'
listen '/home/git/gitlab/tmp/sockets/gitlab.socket'

ドキュメントでは puma で動作するはずなのですが unicorn のようなので unicorn.rb を配置します
また socket ファイルの場所を変更します、これは gitlab-workhorse が見ている socket ファイルの場所がデフォルトだと /home/git/gitlab/tmp/sockets/gitlab.socket になっているためです
次に git の設定を変更します
おそらくこの辺りはコミッター向けの設定かなと思います

  • sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
  • sudo -u git -H git config --global core.autocrlf input
  • sudo -u git -H git config --global gc.auto 0
  • sudo -u git -H git config --global repack.writeBitmaps true
  • sudo -u git -H git config --global receive.advertisePushOptions true
  • sudo -u git -H git config --global core.fsyncObjectFiles true

最後に Redis を使ったワーカーの設定ファイルを配置します

  • sudo -u git -H cp config/resque.yml.example config/resque.yml
  • # sudo -u git -H editor config/resque.yml

DB の設定を行います
こちらも基本的には変更は不要だと思います

  • sudo -u git cp config/database.yml.postgresql config/database.yml
  • # sudo -u git -H editor config/database.yml
  • sudo -u git -H chmod o-rwx config/database.yml

Gem のインストール

ここからは git ユーザに変わって作業することをおすすめします
bundle install の際は「development」「test」を指定しないと rake -T でタスクの一覧が確認できなかったので指定します

  • su - git
  • bundle install --with development test
  • bundle exec rake -T

Gitlab を管理するシェルをインストール

  • su - git
  • bundle exec rake gitlab:shell:install REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production SKIP_STORAGE_VALIDATION=true
  • # editor /home/git/gitlab-shell/config.yml

/home/git/gitlab-shell/bin/gitlab-shell にインストールされます

  • bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production

/home/git/gitlab-workhorse/gitlab-workhorse にインストールされます

なお公式のドキュメントにある「gitlab:indexer:install」はタスクの一覧に 11-8-stable ブランチにはないようです

Gitaly のインストールと起動

  • su - git
  • bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories]" RAILS_ENV=production

/home/git/gitaly/_build/bin/gitaly にインストールされます

  • sudo su -
  • chmod 0700 /home/git/gitlab/tmp/sockets/private
  • chown git /home/git/gitlab/tmp/sockets/private
  • su - git
  • cd /home/git/gitaly
  • # editor config.toml
  • gitlab_path=/home/git/gitlab gitaly_path=/home/git/gitaly && ${gitlab_path}/bin/daemon_with_pidfile ${gitlab_path}/tmp/pids/gitaly.pid ${gitaly_path}/gitaly ${gitaly_path}/config.toml >> ${gitlab_path}/log/gitaly.log 2>&1

ps aux | grep gitaly で 3 つほどプロセスが起動していれば OK です

データベースのマイグレート

この作業には事前に gitaly の起動が必要です

  • sudo su -
  • su - git
  • cd /home/git/gitlab
  • bundle exec rake gitlab:setup RAILS_ENV=production

psql gitlabhq_production -c '\d' を実行すると 294 個のテーブルが作成されていることが確認できると思います

各プロセスの起動スクリプトを配置

  • sudo su -
  • cd /home/git/gitlab
  • cp lib/support/init.d/gitlab /etc/init.d/gitlab
  • cp lib/support/init.d/gitlab.default.example /etc/default/gitlab
  • update-rc.d gitlab defaults 21

ls -l /etc/rc*.d/*gitlab でランレベルなどを確認できます
なお起動スクリプト配置後は gitaly の起動と停止もここから行えます

ログローテションの設定

  • sudo su -
  • cd /home/git/gitlab
  • cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab

状態を確認する

  • sudo su -
  • su - git
  • cd /home/git/gitlab
  • bundle exec rake gitlab:env:info RAILS_ENV=production

ここまでのインストール状況では以下のように表示されました

System information
System:         Ubuntu 16.04
Current User:   git
Using RVM:      yes
RVM Version:    1.29.10
Ruby Version:   2.5.3p105
Gem Version:    2.7.7
Bundler Version:1.16.2
Rake Version:   12.3.2
Redis Version:  3.0.6
Git Version:    2.7.4
Sidekiq Version:5.2.5
Go Version:     go1.13.5 linux/amd64

GitLab information
Version:        11.8.10
Revision:       7d457b7
Directory:      /home/git/gitlab
DB Adapter:     postgresql
URL:            http://localhost
HTTP Clone URL: http://localhost/some-group/some-project.git
SSH Clone URL:  git@localhost:some-group/some-project.git
Using LDAP:     no
Using Omniauth: yes
Omniauth Providers: 

GitLab Shell
Version:        8.4.4
Repository storage paths:
- default:      /home/git/repositories
Hooks:          /home/git/gitlab-shell/hooks
Git:            /usr/bin/git

UI 関連の作業

あとは UI 関連のインストールや設定を行います

GetText PO files の作成

簡単に言えば UI の国際化対応 (ローカライズ) のためのファイルを作成します

  • sudo su -
  • su - git
  • cd /home/git/gitlab
  • bundle exec rake gettext:compile RAILS_ENV=production

アセットファイルの作成

UI のビルドを行い js ファイルを生成します
少し時間がかかります

  • sudo su -
  • su - git
  • cd /home/git/gitlab
  • yarn install --production --pure-lockfile
  • bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production

Gitlab の起動

起動スクリプトを配置してので systemctl or service コマンドで起動できます

  • sudo su -
  • systemctl start gitlab

bundler: failed to load command: unicorn_rails (/home/git/gitlab/vendor/bundle/ruby/2.5.0/bin/unicorn_rails) が出る場合は unicron.rb が設置されているか確認しましょう

Nginx のインストールと設定

xenial デフォルトのリポジトリからインストールできる nginx はバージョンが古いので最新の安定版の nginx をインストールします

  • sudo su -
  • add-apt-repository ppa:nginx/stable
  • apt -y update
  • apt -y install nginx
  • cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab
  • ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
  • rm -f /etc/nginx/sites-enabled/default

nginx -t で config ファイルの間違えをチェックしましょう

  • systemctl restart nginx

動作確認

  • sudo su -
  • su - git
  • cd /home/git/gitlab
  • bundle exec rake gitlab:check RAILS_ENV=production
Checking GitLab subtasks ...

Checking GitLab Shell ...

GitLab Shell: ... GitLab Shell version >= 8.4.4 ? ... OK (8.4.4)
Running /home/git/gitlab-shell/bin/check
Check GitLab API access: OK
Redis available via internal API: OK

Access to /home/git/.ssh/authorized_keys: OK
gitlab-shell self-check successful

Checking GitLab Shell ... Finished

Checking Gitaly ...

Gitaly: ... default ... OK

Checking Gitaly ... Finished

Checking Sidekiq ...

Sidekiq: ... Running? ... yes
Number of Sidekiq processes ... 1

Checking Sidekiq ... Finished

Checking Incoming Email ...

Incoming Email: ... Reply by email is disabled in config/gitlab.yml

Checking Incoming Email ... Finished

Checking LDAP ...

LDAP: ... LDAP is disabled in config/gitlab.yml

Checking LDAP ... Finished

Checking GitLab App ...

Git configured correctly? ... yes
Database config exists? ... yes
All migrations up? ... yes
Database contains orphaned GroupMembers? ... no
GitLab config exists? ... yes
GitLab config up to date? ... yes
Log directory writable? ... yes
Tmp directory writable? ... yes
Uploads directory exists? ... yes
Uploads directory has correct permissions? ... yes
Uploads directory tmp has correct permissions? ... skipped (no tmp uploads folder yet)
Init script exists? ... yes
Init script up-to-date? ... yes
Projects have namespace: ... can't check, you have no projects
Redis version >= 2.8.0? ... yes
Ruby version >= 2.3.5 ? ... yes (2.5.3)
Git version >= 2.18.0 ? ... yes (2.26.2)
Git user has default SSH configuration? ... yes
Active users: ... 1

Checking GitLab App ... Finished


Checking GitLab subtasks ... Finished

まずは必要なプロセスが動作しているか確認しましょう
自分は Update your git to a version >= 2.18.0 from 2.7.4 が出たので git を最新版に変更しました (冒頭で紹介)
最終的にエラーが表示されなければ OK です

あとはブラウザで Ubuntu サーバの IP (自分は vagrant なので 192.168.100.11) にアクセスしましょう
ちゃんと Gitlab にアクセスできることが確認できます

root ユーザのパスワードを設定しプロジェクトの作成ができるか確認してみましょう

コードを直接変更するには

手元にコードがあるので直接変更してみましょう
Gitlab は 192.168.100.11/favicon.png に問い合わせると favicon のアイコンデータが URL にリダイレクトします
修正してトップページリダイレクトされるようにしてみましょう

  • sudo su - git
  • cd /home/git/gitlab
  • vim config/routes.rb
favicon_redirect = redirect do |_params, _request|
  '/'
  #ActionController::Base.helpers.asset_url(Gitlab::Favicon.main)
end
  • sudo systemctl restart gitlab

これで 192.168.100.11/favicon.png に問い合わせるとトップページにリダイレクトされるようになると思います

おまけ: Gitlab Pages のインストールと設定

この操作は任意です
Pages はなくても動作します

  • sudo su - git
  • cd /home/git
  • git clone https://gitlab.com/gitlab-org/gitlab-pages.git
  • cd gitlab-pages/
  • git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
  • make

設定ファイルを変更して Gitlab Pages を有効にします

  • vim config/gitlab.yml
pages:
  enabled: true
  • sudo vim /etc/default/gitlab
gitlab_pages_enabled=true
  • sudo cp lib/support/nginx/gitlab-pages /etc/nginx/sites-available/gitlab-pages.conf
  • sudo ln -sf /etc/nginx/sites-{available,enabled}/gitlab-pages.conf

あとは nginx と gitlab を再起動すれば OK です

  • sudo systemctl restart nginx
  • sudo systemctl restart gitlab

最後に

Gitlab をソースコードからインストールしてみました
Gitlab の仕組みなどを学習したい場合には良いかなと思いますが実際に production で使う場合には Omnibus Install を使いましょう
ソースコードが手元にあるので直接バグを改修したりできるので開発者やデバッガ向けの環境かなと思います

大変だったのは Gitlab のバージョンによる Ruby のバージョンの違いかなと思います
当初は Ruby2.6 で進めていたのですがうまく行かず 2.5 にしました
あとはドキュメントがちょくちょく間違っているのでそこは自力で解決した感じです
Gitlab のログは /home/git/gitlab/log/ にあるのでこのあたりを見ながら解決しました

また後からわかったのですが gitlab-foss は readonly リポジトリになっているようで開発のメインリポジトリをビルドしたい場合は gitlab.org/gitlab をビルドしてみると良いと思います

参考サイト

2020年4月23日木曜日

Gitlab で認証に Google OAuth2 を使ってみた

概要

Gitlab には Ruby の OmniAuth を使ったいろいろな認証連携をサポートしています
今回は Google OAuth2 と連携する方法を紹介したいと思います

環境

  • Ubuntu 16.04
    • GitLab Enterprise Edition 12.9.2-ee
  • Google OAuth2 (2020/04/17 時点)

Google OAuth2 ClientID と ClientSecret を取得する

Google Cloud Platform (GCP) に事前にプロジェクトを作成してある想定です
また OAuth2 のクライアントアプリケーションも作成済みを想定しています
まだの場合はこの辺りを参考に OAuth2 クライアントアプリの作成を行ってください

左メニューから「API サービス」->「認証情報」と進みます

そして右の方にある「クライアントID」と「クライアントシークレット」をメモしておきます

OAuth2 のリダイレクト URL を設定する

次に OAuth2 の認証後に Gitlab に戻ってくるリダイレクト URL を設定します
同じように「API サービス」->「認証情報」と進みます
そして一覧から先程「クライアントID」と「クライアントシークレット」を選択し下にある「URI」と「承認済みのリダイレクト URI」に以下を追加しましょう

このリダイレクト URI は Gitlab が指定する URI なので変更しないようにしましょう
またドメインの部分は自身の環境に合わせたドメインにしてください

external_url を設定する

過去の記事で Gitlab の初期化時に external_url は IP を指定していました
Google OAuth2 のリダイレクト URL には IP アドレスの指定はできないのでローカルで解決できるドメインに変更してあげましょう

  • vim /etc/gitlab/gitlab.rb
external_url 'http://gitlab.example.com'
  • gitlab-ctl reconfigure

そして Mac などのクライアント側に gitlab.example.com を解決する情報を /etc/hosts に追記します

  • sudo vim /etc/hosts
192.168.100.10  gitlab.example.com

gitlab.rb に omniauth_provider の設定を記載する

取得したクライアントID とクライアントシークレットを gitlab.rb に記載します
2 auth factor などを使っていない場合はそのまま同じ設定をすれば動作すると思います
app_id にクライアントID を app_secret にクライアントシークレットを記載します

  • vim /etc/gitlab/gitlab.rb
gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['google_oauth2']
gitlab_rails['omniauth_sync_profile_from_provider'] = ['google_oauth2']
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_providers'] = [
  {
    "name" => "google_oauth2",
    "app_id" => "00000000000-xxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
    "app_secret" => "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "args" => { "access_type" => "offline", "approval_prompt" => "" }
  }
]

omniauth_block_auto_created_users は今回 false にしています
これを false にすると Google OAuth2 で認証後すぐにアカウントが作成されすぐにログインできるようになります
true にしておくとアカウントは作成されるが Admin ユーザがログインを許可しない限りログインはできない状態となります (ブロック状態)
今回はテストなので false にしています

各種パラメータの説明などはこちらが参考になると思います
記載できたら reconfigure をかけましょう

  • gitlab-ctl reconfigure

動作確認

これで Gitlab にアクセスすると Google OAuth のアイコンが追加されています
クリックしてアカウントの作成とログインをしてみましょう

この画面に出てくる情報は GCP の「OAuth の同意画面」で編集できます
アイコンやホームページの情報など正確な情報を載せたい場合には審査が必要になります

これでアカウントの作成とログインができれば OK です
アイコンの情報は読み込まれないようで Gravator と連携するようなので必要であれば Gravator に登録したり自分で Gitlab にアイコンをアップロードしましょう

OAuth 後に以下の画面が出てうまくログインできない場合は gitlab.rb のパラメータの設定を確認してみてください

最後に

Gitlab で Google OAuth2 と連携してみました
今回はアカウントの作成後すぐにログインできるようにしていますが安全にするならブロックを true にしても良いかもしれません

他にも SAML や OpenID との連携もできるのですでに ID 管理している機構がありそれらのインタフェースを持っているなら簡単に連携可能です

Tips: Google アカウントが許可したアプリの一覧を確認するには

ここから Gitlab にログインするために許可したアプリが確認できます
テストなどでもう使わないのであれば権限を削除しておきましょう

参考サイト

2020年4月22日水曜日

Gitlab で redis-server を外部サーバに移行してみた

概要

前回 Gitlab の Postgres のプロセスを外部のサーバに移行してみました
Gitlab は内部で redis-server も動作しています
主に非同期処理を担っている Sidekiq が使っています
今回は redis-server を外部のサーバに移行する方法を紹介します

環境

  • Ubuntu 16.04
    • GitLab Enterprise Edition 12.9.2-ee
  • macOS 10.15.4
    • PostgreSQL 12.2

redis-server の設定

まずは redis 側の設定を行います
なお今回は redis は単体で動作させるので sentinel などは考慮していません
Gitlab 自体は sentinel にも対応しているので sentinel 環境でも動作します

bind アドレスの変更

  • vim /usr/local/etc/redis.conf
bind 192.168.100.1

後に書かれている設定が有効になるので注意してください

  • brew services start redis

Gitlab の設定

次に Gitlab 側の設定変更を行います
基本的には gitlab.rb に記載されている redis のエンドポイントを変更するだけです

  • vim /etc/gitlab/gitlab.rb
gitlab_rails['redis_host'] = "192.168.100.1"

パスワードの指定やポートの指定がある場合は redis_passwordredis_port の指定もしてください
あとは reconfigure すれば OK です

  • sudo gitlab-ctl reconfigure
  • sudo gitlab-ctl start

動作確認

redis-cli でアクセスしてみましょう
うまく起動していれば外部の redis-server に以下のようなキーが生成されているはずです

resque:gitlab:stat:failed:2020-04-16
resque:gitlab:cron_job:schedule_migrate_external_diffs_worker:enqueued
resque:gitlab:cron_job:sync_seat_link_worker:enqueued
resque:gitlab:cron_job:gitlab_usage_ping_worker:enqueued
resque:gitlab:cron_job:adjourned_projects_deletion_cron_worker:enqueued
resque:gitlab:cron_jobs
resque:gitlab:cron_job:environments_auto_stop_cron_worker
resque:gitlab:cron_job:environments_auto_stop_cron_worker:enqueued
resque:gitlab:cron_job:geo_container_repository_sync_worker:enqueued
cache:gitlab:flipper/v1/feature/prometheus_metrics_view_instrumentation
・・・

一部省略していますが起動するだけで 120 ほどキーが作成されました

動作確認

プロジェクトの作成/削除が行えるか確認してみましょう
問題なければ redis が正常に動作しています

おまけ: flushall したらどうなるか

試してに redis 上のデータが全部なくなったら Gitlab が動作するのが試してみました
Gitlab が起動している状態で FLUSHALL コマンドを発行してみます

192.168.100.1:6379> FLUSHALL
OK
192.168.100.1:6379> keys *
1) "resque:gitlab:ubuntu-xenial:5873:8e3f66aefc21"
2) "resque:gitlab:stat:processed:2020-04-16"
3) "resque:gitlab:stat:failed:2020-04-16"
4) "resque:gitlab:processes"
5) "resque:gitlab:stat:processed"
6) "resque:gitlab:reliable-fetcher-heartbeat-ubuntu-xenial-5873"
7) "resque:gitlab:stat:failed"

いくつかのキーは削除と同時にすぐに作成されました
この状態で Gitlab にアクセスするとユーザはログアウトした状態になりました
おそらくはセッショントークンの情報は redis で管理しているためだと思います
またそれ以外のページの移動は問題なく行えました
やはりキャッシュ的な使い方がメインでキャッシュがない場合は再度生成するだけなのでシステム的にはデータが消えても大きな問題にはならないようです

最後に

Gitlab のコンポーネントの一部である redis を外部に移行してみました
Postgres に比べるとデータの移行はなさそうなので簡単に移行できると思います

外部に移行するこで VM の役割が明確になりまた運用するコマンドも純正の redis-cli などが使えるのでやりやすくなると思います
Sentinel と組み合わせれば更に安定したアーキテクチャにすることができます

参考サイト

2020年4月21日火曜日

Gitlab でデータベースを外部のサーバに設定する方法

概要

Gitlab を Ubuntudocker にインストールしましたがどちらもデータベースや Web などがすべて同じ VM or コンテナないで動作していました
スケールや SPOF を考えると別の VM に移動したいケースがあると思います
今回は Gitlab のデータベースである PostgreSQL を外部のサーバに移動してみたのでその移行方法やデータのマイグレーション方法を紹介します

環境

  • Ubuntu 16.04
    • GitLab Enterprise Edition 12.9.2-ee
  • macOS 10.15.4
    • PostgreSQL 12.2

データベースサーバ側の設定

今回は Postgres を使うので Postgres の設定ファイルを編集します
なお Postgres は Mac 上で動作している Postgres を使います

Gitlab 用の Postgres のデータディレクトリ作成

  • mkdir /usr/local/var/postgres_gitlab
  • initdb /usr/local/var/postgres_gitlab
  • pg_ctl -D /usr/local/var/postgres_gitlab start

gitlabhq_production データベース作成

  • psql -U hawksnowlog postgres

SQL のプロンプトに変更したら CREATE DATABASE コマンドでデータベースを作成します

  • CREATE DATABASE gitlabhq_production OWNER gitlab;

Postgres に gitlab 用のユーザ作成

  • psql -U hawksnowlog postgres

SQL のプロンプトになったらユーザを作成します

  • create user gitlab with password 'gitlab_secret';
  • select username from pg_user;

スーパーユーザの権限を付与する

  • psql -U hawksnowlog postgres

SQL のプロンプトになったら権限を付与します

  • ALTER ROLE gitlab WITH SUPERUSER;
  • select username from pg_user;
postgres=# select * from pg_shadow; usename | usesysid | usecreatedb | usesuper | userepl | usebypassrls | passwd | valuntil | useconfig ————–+———-+————-+———-+———+————–+————————————-+———-+———– hawksnowlog | 10 | t | t | t | t | | | gitlab | 16384 | f | t | f | f | md5132c2d15e04e6d423de7a687ec9b0d32 | | (2 rows)

外部からアクセスできるようにする

まずは LISTEN するアドレスを localhost から変更します

  • vim /usr/local/var/postgres_gitlab/postgresql.conf
listen_addresses = '192.168.100.1'

0.0.0.0 でも良いですが CIDR or IP が決まっている場合はしっかり設定しましょう
次に接続できるクライアントの CIDR or IP を変更します

vim /usr/local/var/postgres_gitlab/pg_hba.conf

host    all             all             192.168.100.0/24            trust

ここも同様でしっかり設定しましょう
設定変更できたら restart します
設定が反映されているか一度 Gitlab のサーバからアクセスしてみても良いと思います

  • pg_ctl -D /usr/local/var/postgres_gitlab restart
  • netstat -an | grep 5432

Gitlab サーバ側に psql コマンドがあれば以下のコマンドで接続確認できます

  • psql -h 192.168.100.1 -U gitlab gitlabhq_production

Gitlab 側の設定変更

ここからは Gitlab の設定を変更します
Ubuntu にインストールしているので Ubuntu 上で作業します

gitlab.rb の修正

Gitlab は Ubuntu に apt で事前にインストールしていることを想定しています
gitlab.rb という設定ファイルを編集します

  • vim /etc/gitlab/gitlab.rb
gitlab_rails['db_username'] = "gitlab"
gitlab_rails['db_password'] = "gitlab_secret"
gitlab_rails['db_host'] = "192.168.100.1"
  • sudo gitlab-ctl reconfigure
  • sudo gitlab-ctl start

これで 192.168.100.10 にアクセスすると Gitlab が立ち上がりかつ外部のデータベースに接続されているのが確認できると思います
なおデータはマイグレートしていないので完全に初期化状態になります

データをマイグレートするには

ダンプファイルを作成してそれをそのままインポートすれば良さそうです
試しにやってみたのでメモしておきます

  • vim /etc/gitlab/gitlab.rb
  • gitlab-ctl reconfigure
  • gitlab-ctl start

で先程の部分を元に戻してローカルで動作させます
pg_dumpall が古い場合は最新版に差し替えます (差し替え方法は後述しています)

  • sudo mv /opt/gitlab/embedded/postgresql/10/bin/pg_dumpall{,.back}
  • sudo ln -s /usr/bin/pg_dumpall /opt/gitlab/embedded/postgresql/10/bin/
  • sudo -i -u gitlab-psql -- /opt/gitlab/embedded/bin/pg_dumpall > ./database.sql

データが少ない場合はすぐに終わります
警告やエラーが出る場合は実行しているユーザを確認してください (上記は vagrant ユーザで実行しています)
あとはダンプファイル database.sql を Mac 側にリストアすれば OK です
ただ自分が試した感じだと gitlabhq_production を一度削除して空にしてからリストアしないとダメな感じでした
おそらく auto_increment などによる影響かなと思います

  • pg_ctl -D /usr/local/var/postgres_gitlab start
  • psql postgres
    • DROP DATABASE gitlabhq_production;
    • CREATE DATABASE gitlabhq_production OWNER gitlab;
  • psql -f /path/to/database.sql gitlabhq_production

これで再度 gitlab.rb を編集して reconfigure -> start をかければデータの移行が完了しているはずです

Gitlab のデータを丸々バックアップするには

gitlab-rake gitlab:backup:creategitlab-rake gitlab:backup:restore を使います

まずは Ubuntu 側 (元のデータがあるサーバ) で

  • gitlab-rake gitlab:backup:create

を実行します
バックアップの作成が成功すると /var/opt/gitlab/backups/1586997709_2020_04_16_12.9.2-ee_gitlab_backup.tar が作成されます

この方法はデータベースサーバだけでなく Gitlab 自体を別のサーバに移行する際に使える方法です

psql コマンドが最新でない場合には

Ubuntu16.04 のデフォルトのリポジトリからは 9.5.21 の postgresql-client しかインストールできません
PostgreSQL サーバのバージョンが最新の場合はクライアント側も最新にしなければいけないので以下のように最新版をインストールしましょう

  • sudo apt-get install curl ca-certificates gnupg
  • curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
  • sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
  • apt -y update
  • apt -y install postgresql-client-12

pg_dump -V コマンドでバージョンがを確認してサーバ側と同じバージョンになっていれば OK です
それでも古いバージョンの pg_dump を使おうとする場合は強制的にバイナリを変更しても良いと思います

  • mv /opt/gitlab/embedded/postgresql/10/bin/pg_dump{,.back}
  • ln -s /usr/bin/pg_dump /opt/gitlab/embedded/postgresql/10/bin/

最後に

Gitlab で Postgres を外部のサーバに移行する方法を紹介しました
gitlab の reconfigure と restart が入るので完全に無停止で移行するのは難しそうです
また Gitlab に含まれている pg_hogehoge 系のコマンドが古いので、移行先の Postgres のバージョンに合わせてコマンドを差し替えないとうまく動作しない場合がありそうです

またどうやら Nginx や Redis、Gitaly など Gitlab を構成する主要コンポーネントは外部に移行できるようなので他のコンポーネントを外部にする方法も別記事で紹介したいと思います

参考サイト

2020年4月20日月曜日

(mcaselector 編) Minecraft の mca ファイルを使ってチャンクデータを確認する方法

概要

前回 minecraft-chunk-viewer を使って mca ファイルの中身を確認する方法を紹介しました
しかし 1.15 には対応しておらず上手く動作しませんでした
今回は mcaselector という Java 版の mca ビューアを紹介します
インストールから簡単な使い方まで紹介します

環境

  • macOS 10.15.4
  • Java 10.0.1
  • mcaselector 1.9.8

mcaselector のダウンロード

mcaselector も Github でソースが公開されています
ダウンロードも Github から行います

執筆時点では「mcaselector-1.9.8.jar」という jar ファイルがダウンロードされました

実行してみる

ダウンロードした jar ファイルをダブルクリックで起動してみましょう
当然ですが Java がインストールされていないと起動しません
Mac の場合は右クリックから開くを選択します
また Java が権限を求めてくるのでシステムの環境設定を開いて許可しましょう

起動すると以下のような画面になります

メニューから File -> Open を選択します
そして Minecraft のセーブファイルがあるディレクトリに移動し region ディレクトリを選択しましょう
region ディレクトリ配下には mca ファイルが管理されておりディレクトリを選択することですべての mca ファイルを開くことができます

使い方

画面を一番拡大で見ると読み込まれた mca ファイルがだいたい確認できると思います

縮小していくと建築物や村の様子も確認することができます

自分の行ったことがある場所の地形までしか確認することができないのでまだ塗りつぶされていないところは行ってないことになります
キノコバイオームなどは赤い点があったりするのでバイオームなどがどこにあるのかの確認は簡単にできそうです

「A」「W」「S」「D」で移動もできました

エンドやネザーを開くには

Minecraft の saves 配下に「DIM1」と「DIM-1」というフォルダがあります
DIM1 と DIM-1 配下にも region というフォルダがありそれぞれエンドとネザーの mca データになります

これを再度 File -> Open で開けばエンドとネザーのマップを確認することができます

お宝などを復元できる

これを使うと mca を直接編集できマップを削除することができます
マップを削除するとまだ行っていないことになりチェスト内のお宝などを復元することができるようです
完全にチート行為にはなるのでやる方は自己責任でお願いしますがこれを使えばレアなダンジョンや要塞を再度チャレンじすることもできます

最後に

mcaselector を使って mca ファイルを開きすでに行ったことのあるマップを確認する方法を紹介しました
行ったことがあるけどどこか忘れてしまった場合は上空から建築物がちゃんとできているかなどの確認に使えそうです

mcaselector はマップの削除もできるようでこれを使えばすでに行った場所を行ってない状態に戻すことができるようです

参考サイト

2020年4月19日日曜日

Minecraft の mca ファイルを使ってチャンクデータを確認する方法

概要

Minecraft は mca と呼ばれる独自のファイルを使ってマップデータを管理しています
バイナリデータなので特殊な方法でなければ開けません
minecraft-chunk-viewer は WebGL を使ってブラウザでマップデータを確認することができます
今回は minecraft-chunk-viewer の使い方を紹介したいと思います

環境

  • macOS 10.15.4
  • nodejs 10.1.0
  • npm 5.6.0

リポジトリの clone

  • git clone https://github.com/Pessimistress/minecraft-chunk-viewer.git

jar ファイルの展開

minecraft 本体に含まれる jar ファイルから assets フォルダを抽出します
まずは jar ファイルを解凍しましょう

  • mkdir /path/to/1.15.2
  • cd /path/to/1.15.2
  • cp ~/Library/Application\ Support/minecraft/versions/1.15.2/1.15.2.jar .
  • jar -xvf 1.15.2.jar

assets ディレクトリの移動

そして clone したリポジトリの直下に jar 内に含まれる assets フォルダ配下のリソースを移動します

  • cd minecraft-chunk-viewer
  • mkdir assets
  • mv /path/to/1.15.2/assets/minecraft/* ./assets
  • cp -ipr ./assets/textures/block ./assets/blocks

また minecraft 1.15 ではブロックを管理するフォルダの名前が変わっているので viewer が使えるように名前を変更します
ただやはり 1.15 にはまだ対応していないのか blocks/red_nether_brick.png could not be loaded などのエラーが出るので今後修正が入るかもしれません

npm install

  • npm install

npm run build-assets

  • npm run build-assets

npm start

  • npm start

これで Web アプリが localhost:3000 で起動します
初回起動されるデータはサンプルの mca ファイルのようです

1 チャンクごとに表示されます
画像が対応していないところはおそらくブロックが表示されていません

トラックパッドで回転や拡大、移動などができます
右下のマップから好きなチャンクを選択することができます
ブロックを選択すると座標を確認することができます

また mca ファイルを画面にドロップすれば好きな mca ファイルを確認することができます
ちなみに自分のゲームデータの mca ファイルは /path/to/minecraft_dir/saves/world_name/region/ 配下にあります
※試してみましたが 1.15 の mca ファイルにはどうやら対応していないらしく動作しませんでした
一応デプロイ済みの Web 版 もあるようですがこれも未対応でした

最後に

Minecraft のマップファイルを管理している mca ファイルを minecraft-chunk-viewer を使って確認してみました
まだ 1.15 には対応していないようです
1.14 の aseets データを使っても良いかもしれません

2020年4月18日土曜日

Rails6 + Sidekiq 超入門

概要

前回 Rails6 と PostgreSQL を使って簡単な Web アプリを作ってみました
今回は Rails6 と Sidekiq を組み合わせて非同期な Web アプリを作ってみます

Redis のインストール

  • brew install redis
  • brew services start redis

Sidekiq のインストール

rails new で作成したアプリ配下にある Gemfile を編集します

  • vim Gemfile
gem "sidekiq"
  • bundle install

Sidekiq の初期化

config/initializers/sidekiq.rb を作成してここに Redis のエンドポイントなど Sidekiq の初期化に必要なパラメータなどを設定します

  • vim config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://localhost:6379/0' }
end

Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://localhost:6379/0' }
end

Worker の作成

app/workers 配下に作成します
デフォルトだとディレクトリが存在しないので作成します
ワーカーのファイル名は名前はワーカークラス名のスネークケースで作成します

  • mkdir app/workers
  • vim app/workers/wait_worker.rb
class WaitWorker
  include Sidekiq::Worker

  def perform(time, params)
    sleep time
    my_task = MyTask.new
    params = JSON.parse(params)
    my_task.title = params["title"]
    my_task.description = params["description"]
    my_task.public = params["public"]
    my_task.updated_date = Time.now
    if my_task.public
      my_task.posted_date = Time.now
    end
    my_task.save
  end
end

Sidekiq を経由すると params の Rails 側アプリとは少し異なる点に注意してください
後述していますがハッシュを JSON 文字列に変換してから Sidekiq に渡しています
やっていることは前回のタスクを登録する処理と同じです

エンキューする処理の実装

Rails アプリ側でエンキューするようにしましょう
コントローラを修正します

  • vim app/controllers/my_tasks_controller.rb
class MyTasksController < ApplicationController
  protect_from_forgery

  def list
    @my_tasks = MyTask.order(posted_date: "DESC").all
  end

  def show
    id = params[:id]
    @my_task = MyTask.find(id)
  end

  def create
    WaitWorker.perform_async(5, params.to_json)
    redirect_to '/my_tasks'
  end
end

1 つポイントがあり Sidekiq にハッシュ値を渡したい場合は一旦 JSON 文字列に変換する必要があります
そしてワーカー側で JSON 文字列からハッシュに再度変換します
今回は適当に遅延させたいので 5 秒ウェイトしてから DB に INSERT します

動作確認

まずはワーカーを起動します

  • bundle exec sidekiq

そして Rails アプリを起動しましょう

  • rails server

あとはタスクを作成してみましょう
5 秒ほど遅延があってからデータが挿入されるのが確認できると思います

最後に

Rails6 + Sidekiq を試してみました
Rails 上で使う場合はディレクトリ構成が決まっているのでその点だけ注意が必要かなと思います
Rails 上の場合は require 系が不要なのが記述が少なく済むので嬉しいのかなと思います

参考サイト

2020年4月17日金曜日

Rails6 + PostgreSQL 超入門

概要

備忘録として Rails6 + postgresql の簡単なチュートリアル記事を残しておきます
Rails を久しぶりに使うときの導入記事として使いたいと思っています
ただバージョンによってかなり挙動や必要なツールが異なるのでその辺りはバージョンに応じて適宜対応してください

環境

  • macOS 10.15.4
  • Ruby 2.7.1p83
  • Rails 6.0.2.2
  • Postgres 12.2
  • nodejs 13.12.0

事前準備

  • gem install rails

グローバルにインストールしました
本当は bundle init してローカルインストールにしたかったのですがうまく動作しなかったので辞めました

PostgreSQL のインストールと起動

Postgres がまだインストールされていない場合はインストールしましょう

  • brew install postgresql
  • pg_ctl -D /usr/local/var/postgres start

停止したい場合は stop すれば OK です

  • pg_ctl -D /usr/local/var/postgres stop

nodejs/yarn のインストール

なぜか内部的に nodejs も使っているのでインストールします
webpack などの関係かなと思いますがとりあえず素直に入れます

  • brew install node
  • npm install -g yarn

新規アプリ作成

お決まりの TODO アプリになります
Postgres を使ったアプリを作成するので -d postgresql を忘れないようにしましょう

  • rails new todo -d postgresql

大量の gem がインストールされるので待ちます
スモールスタートしたいのにこの大量の gem をインストールするのがあまり好きになれないところでもあります

データベース作成

以下は作成したアプリのディレクトリ内で行います

  • cd todo
  • rake db:create RAILS_ENV=development

これで todo_developmenttodo_test というデータベースが作成されます
psql -l コマンドなどで直接 Postgres に問い合わせても確認できます

データベースをマイグレート

  • rails generate migration create_my_tasks

これでマイグレーションファイル db/migrate/20200415012753_create_my_tasks.rb が作成されるので編集します

  • vim db/migrate/20200415012753_create_my_tasks.rb
class CreateMyTasks < ActiveRecord::Migration[6.0]
  def change
    create_table :my_tasks do |t|
      t.string :title
      t.text :description
      t.timestamp :posted_date
      t.timestamp :updated_date
      t.boolean :public
    end
  end
end
  • rake db:migrate RAILS_ENV=development

これで todo_development データベース内に my_tasks というテーブルが作成されました

% psql todo_development psql (12.2) Type "help" for help.   todo_development=# \d my_tasks Table "public.my_tasks" Column | Type | Collation | Nullable | Default ————–+—————————–+———–+———-+————————————– id | bigint | | not null | nextval('my_tasks_id_seq'::regclass) title | character varying | | | description | text | | | posted_date | timestamp without time zone | | | updated_date | timestamp without time zone | | | public | boolean | | | Indexes: "my_tasks_pkey" PRIMARY KEY, btree (id)

新規モデル作成

作成した my_tasks テーブルを扱うモデルを作成します
すでにマイグレーションファイルは作成しているので --skip を指定します
g model はマイグレーションファイルも作成してくれるようなので g migration を実行しないで g model だけ実行しても良いと思います

  • rails generate model my_task --skip

app/models/my_task.rb が作成されれば OK です
test/models/my_task_test.rbtest/fixtures/my_tasks.yml はテスト用のファイルになります
ちなみにモデルは単数形で DB のテーブル名は複数形になります

コントローラ作成

実際に Web アプリのハンドリングを行うコントローラを生成します
my_tasks を CRUD するためのコントローラを作成しましょう

  • rails g controller my_tasks

ggenerate の省略形になります
慣れたら省略形を使ったほうが楽です

app/controllers/my_tasks_controller.rbapp/views/my_tasksapp/helpers/my_tasks_helper.rb が主なファイルになります
あとはスタイルシート用の .scss ファイルとテスト用のファイルも作成してくれます

routes.rb でルーティングを設定する

どの URL にアクセスしたらどのメソッドを実行するか定義します
ようやくこの辺りからプログラミングっぽくなってきます

  • vim config/routes.rb
Rails.application.routes.draw do
  get 'my_tasks', to: 'my_tasks#list'
  get 'my_tasks/:id', to: 'my_tasks#show'
  post 'my_tasks', to: 'my_tasks#create'
end

とりあえず今回は簡単な「取得」と「作成」だけ実装します
大抵の「更新」や「削除」なども必要になると思うので余裕があれば実装してみましょう

コントローラにルーティングされるメソッドを実装する

とりあえず一番簡単そうな list を実装してみましょう

  • vim app/controllers/my_tasks_controller.rb
class MyTasksController < ApplicationController
  def list
    @my_tasks = MyTask.order(posted_date: "DESC").all
  end
end

MyTask はモデルになります
コントローラからモデルの呼び出しは require 等は不要で参照できます
全件取得する場合は .all を使います
内部的には単純に SELECT * が実行されています

今回は order を使っていますが他にも様々な SQL 構文を実行できるので興味があればこちらのリファレンスを御覧ください

View を作成する

実際に HTML として出力されるテンプレートを作成します
先程コントローラで Postgres から取得した @my_tasks の情報を HTML として出力してあげます
また一覧から登録もできるようにするため form も設置しています
create メソッドは後述するためまだ動作はしません

メソッド名と同じ erb ファイルは所定の場所に配置すると自動的にそれを呼び出してくれるようです

  • vim app/views/my_tasks/list.erb
<html>
  <head><title>List My Tasks</title></head>
<body>
<h2>Create My Task</h2>
<form method="POST" action="/my_tasks">
  <p>Title: <input type="text" name="title"></p>
  <p>Description: <br><textarea name="description" rows="4" cols="40"></textarea></p>
  <p>Public: <input type="checkbox" name="public" value="checked"></p>
  <p><button type="submit">Create</button></p>
</form>
<h2>List My Tasks</h2>
<ul>
<% @my_tasks.each do |my_task| %>
  <li>Title: <a href="/my_tasks/<%= my_task.id %>"><%= my_task.title %></a> Posted Date: <%= my_task.posted_date %></li>
<% end %>
</ul>
</body>
</html>

とりあえず動作確認する

この状態でアプリは動作するようになっています
まだデータは何もないので特に表示はされませんが HTML がエラーなく出力されることを確認できると思います

  • rails server

localhost:3000 にアクセスすれば確認できます

post, show を実装する

残りのメソッドをコントローラに実装します

  • vim app/controllers/my_tasks_controller.rb
class MyTasksController < ApplicationController
  protect_from_forgery

  def list
    @my_tasks = MyTask.order(posted_date: "DESC").all
  end

  def show
    id = params[:id]
    @my_task = MyTask.find(id)
  end

  def create
    my_task = MyTask.new
    my_task.title = params[:title]
    my_task.description = params[:description]
    my_task.public = params[:public]
    my_task.updated_date = Time.now
    if my_task.public
      my_task.posted_date = Time.now
    end
    my_task.save
    redirect_to '/my_tasks'
  end
end

protect_from_forgery は CSRF (ActionController::InvalidAuthenticityToken) 対策になります
特に説明することはないと思いますが showparams[:id] を取得して特定の id のタスクの詳細を表示します

create は form から送られてきた情報を params から取得し MyTask モデルのインスタンスにセットします
あとは .save をコールすれば Postgres にデータが格納されます
格納後は /my_tasks にリダイレクトします

show.erb

詳細を表示するページも作成します

<html>
  <head><title>Show My Task</title></head>
<body>
<h2>Show My Task</h2>
  <p>ID: <%= @my_task.id %></p>
  <p>Title: <%= @my_task.title %></p>
  <p>Description: <%= @my_task.description %></p>
  <p>Posted Date: <%= @my_task.posted_date %></p>
  <p>Updated Date: <%= @my_task.updated_date %></p>
  <p>Public: <%= @my_task.public %></p>
</body>
</html>

動作確認

これで今回実装するべきすべての機能を実装しました
アプリを起動して動作確認してみましょう

  • rails server

localhost:3000 にアクセスすると以下のようにデータの登録から確認までができるようになっていると思います

最後に

Rails6 + PostgreSQL で超簡単な Web アプリを作成してみました
超入門レベルの流れは掴めたかなと思います
Controller と Model の連携方法、Controller からどうやって View が呼び出されるか変数が渡せるか、辺りを理解できれば OK かなと思います

Rails は実装よりも新規アプリ作成時のエラー対応の方が大変なイメージがあります

2020年4月16日木曜日

Ubuntu 16.04 に Gitlab をインストールしてみた

概要

過去の記事では docker 上で gitlab を動作させていました
今回は VM にインストールしてみます
対象の OS は Ubuntu16.04 (xenial64) になります

環境

  • Ubuntu 16.04.6 (on Virtualbox)
    • VirtualBox 6.0.18r136238
    • vagrant 2.2.7
  • GitLab Enterprise Edition 12.9.2-ee

Ubuntu の起動

何でも OK です
今回は Vagrant を使います

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"
  config.vm.network "private_network", ip: "192.168.100.10"
  config.vm.provider "virtualbox" do |vb|
    vb.memory = 2024
    vb.cpus = 2
  end
end
  • vagrant up --provider=virtualbox
  • vagrant ssh

Gitlab のインストール

公式の手順に沿ってインストールしていきます
なお apt を今回は使いますが apt 経由の場合は Enterprise Edition のみがインストール可能です

1. 事前準備

  • sudo apt -y update
  • sudo apt install -y curl openssh-server ca-certificates

localhost を使ってメールを送信する場合は postfix もインストールしましょう
外部の SMTP サーバを使ってメール送信する場合は Gitlab 起動後に設定すれば OK です

  • sudo apt -y install postfix

2. Gitlab インストール

専用のリポジトリがあるので追加します

  • curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash

リポジトリの追加と apt update をしてくれます

  • sudo EXTERNAL_URL="http://192.168.100.10" apt -y install gitlab-ee

内部では chef が実行されるのでインストールまでに結構時間がかかります
また apt でインストールする場合は Enterprice Edtion しかないようです

Tips: Chrome は 301 をキャッシュしてしまう

ドキュメントだと EXTERNAL_URL="https://gitlab.example.com" になっていますが上手くアクセスできないことがあったので IP に変更しています
どうやら Chrome は 301 のリダイレクトをキャッシュするようで一度失敗すると失敗し続けてしまいます
キャッシュを削除しても上手くいかず Developer Tools から Network タブを開いて「Disable cache」にチェックを入れるとうまくアクセスできるようです

プロセス確認

プロセスの管理は gitlab-ctl というコマンドを使うようです

  • sudo gitlab-ctl status
run: alertmanager: (pid 13636) 417s; run: log: (pid 1374) 782s
run: gitaly: (pid 1402) 782s; run: log: (pid 1396) 782s
run: gitlab-exporter: (pid 13648) 417s; run: log: (pid 1382) 782s
run: gitlab-workhorse: (pid 13650) 416s; run: log: (pid 1376) 782s
run: grafana: (pid 13627) 418s; run: log: (pid 13616) 426s
run: logrotate: (pid 13662) 416s; run: log: (pid 1377) 782s
run: nginx: (pid 13619) 425s; run: log: (pid 1380) 782s
run: node-exporter: (pid 13670) 416s; run: log: (pid 1379) 782s
run: postgres-exporter: (pid 13676) 415s; run: log: (pid 1375) 782s
run: postgresql: (pid 1390) 782s; run: log: (pid 1378) 782s
run: prometheus: (pid 13685) 415s; run: log: (pid 1394) 782s
run: redis: (pid 1388) 782s; run: log: (pid 1383) 782s
run: redis-exporter: (pid 13697) 414s; run: log: (pid 1391) 782s
run: registry: (pid 13699) 414s; run: log: (pid 1392) 782s
run: sidekiq: (pid 13711) 414s; run: log: (pid 1389) 782s
run: unicorn: (pid 13717) 414s; run: log: (pid 1372) 782s

かなりのプロセスが動作しているのが確認できると思います

アクセス

今回の手順であれば http://192.168.100.10 に Firefox でアクセスすれば Gitlab のページが表示され root ユーザのパスワードとプロジェクトの作成を行います

再度セットアップしたいときは

/etc/gitlab/gitlab.rb などを編集してその値を再度適用したい場合は

  • sudo gitlab-ctl reconfigure

を実行しましょう
プロセスも再起動したい場合は restart で全プロセスを再起動できます

  • sudo gitlab-ctl restart

完全に停止したい場合は stop を使います

  • sudo gitlab-ctl stop

最後に

Ubuntu 16.04 に Gitlab をインストールしてみました
インストール自体は apt のみなので非常に簡単ですがインストールしたあとに設定ファイルを編集してカスタマイズできるようになるまでにはかなり時間がかかりそうです

また今回は 1 台の VM にすべてのコンポーネントがインストールされましたが postgers や redis などを別 VM にする方法も紹介したいと思います

参考サイト