2020年5月31日日曜日

Mac で chef-solo を実行してみた

概要

Mac で chef-solo を実行し mac 自体をプロビジョニングする方法を紹介します

環境

  • macOS 10.15.5
  • Ruby 2.7.1p83
    • chef 16.1.16
    • knife-solo 0.7.0

chef のインストール

chef-workstation をインストールします
これに chef-solo も含まれています
これは chef を使うのに必要なツールなどが一式揃っているツール群になります

  • brew cask install chef-workstation

or

  • sudo curl -L http://www.opscode.com/chef/install.sh | sudo zsh

のどちらからでインストールします
どちらも dmg からインストールする方式なのでインストールされるものは同じです
gem install chef だと chef コマンドが使えませんでした

テスト用の cookbook の作成

  • mkdir ~/try_chef
  • cd ~/try_chef
  • mkdir -p cookbooks/test/recipes

レシピ作成

  • vim cookbooks/test/recipes/default.rb
file "#{ENV['HOME']}/hoge.txt" do
  action :touch
end

とりあえずホームディレクトリに空のファイルを作成するだけのレシピです

node ファイルの作成

  • vim localhost.json
{
  "run_list": [
    "recipe[test]"
  ]
}

作成した test cookbook を実行するようにします

solo.rb の作成

cookbook のパスや nodes, roles を管理するディレクトリを指定します
今回はカレント配下に作成しているので相対パスですが絶対パスで書いても OK です

  • vim solo.rb
cookbook_path    ["cookbooks", "site-cookbooks"]
node_path        "nodes"
role_path        "roles"
environment_path "environments"
data_bag_path    "data_bags"

node_pathrole_path は今回作成していませんがとりあえず指定しています

実行してみる

あとは実行するだけです

  • chef-solo -j ./test.json -c ./solo.rb

これで ~/hoge.txt が作成されているのが確認できると思います

おまけ: knife solo 経由で実行するには

knife solo というツールを使うと chef-solo を ssh 経由で実行できます
一応試したのですが knife solo prepare が macOS 10.15 に対応してないので諦めました

knife-solo のインストール

chef-workstation が使っている gem を使って knife-solo をインストールします

  • brew install coreutils
  • /opt/chef-workstation/embedded/bin/gem install knife-solo

or

  • sudo /opt/chef/embedded/bin/gem install knife-solo

Homebrew の場合は上で Omnibus Install の場合は下を使います

knife プロジェクトの初期化

knife solo init で初期化します
カレントディレクトリを指定しているので注意してください

  • mkdir ~/try_chef2
  • cd ~/try_chef2
  • knife solo init .

cookbook の作成

chef コマンドを使うと雛形を作成してくれます
これ自体は knife solo とは関係ないので chef-solo のみの場合でも使えます

  • chef generate cookbook cookbooks/test

knife solo prepare して chef-solo を実行できる準備をする

ここで失敗しました

  • knife solo prepare localhost

ERROR: RuntimeError: OS X version 10.15.5 not supported」となりました
もしこれができればあとはレシピと node ファイルを作成して

  • knife solo cook localhost ./test.json

すれば OK です

mac 上で localhost に ssh ログインできるようにするには

環境設定から「共有」を選択します
そして「リモートログイン」にチェックを入れれば OK です
knife solo を実行するユーザが ssh できるようにユーザを追加するのを忘れないようにしましょう

最後に

Mac 上に chef-solo をインストールし Mac 自体をプロビジョニングするレシピを作成して動かしてみました
Mac から vagrant などをプロビジョニングする方法は紹介されているのですが Mac 自体をプロビジョニングする記事があまりなかったので紹介してみました

chef-solo をインストールするのが一番大変でした

2020年5月30日土曜日

Yasnippet で yard のドキュメントテンプレートを管理する

概要

emacs で Ruby を編集している際に Yard ドキュメントを補完してほしくなったので Yasnippet にテンプレートを補完してみました

環境

  • macOS 10.15.4
  • emacs 25.3.1
    • yasnippet 0.14.0

Yasnippet インストール

  • M-x package-list-packages

melpa がダメな場合は gnu からで良いと思います

新規スニペット登録

ここの情報を元にスニペットを登録していきます

  • M-x yas-new-snippet

or

  • C-c C-n

最初は以下のような情報しかありません
key はスニペットを呼び出す際の名前になります
基本は同じ内容を登録すれば良いと思います

# -*- mode: snippet -*-
# key:
# name:
# --

key, name を決めたらすぐ下に登録したいスニペットを記載します
今回は yard のドキュメント情報なのでコメントが先頭がシャープになっていますがシャープにする必要はありませんのでご注意ください

# -*- mode: snippet -*-
# key: yard-method-abstract
# name: yard-method-abstract
# --
# An alias to {Parser::SourceParser}'s parsing method
# 
# @author hawksnowlog
#
# @see http://example.com Description of URL
# @see SomeOtherClass#method
#
# @deprecated Use {#my_new_method} instead of this method because
#   it uses a library that is no longer supported in Ruby 1.9. 
#   The new method accepts the same parameters.
#
# @abstract
# @private

あとは保存すれば OK です
保存の際にスニペットを使うモードを指定するので今回は ruby-mode を指定します

  • C-c C-c (Save)
  • ruby-mode (Select mode)

.emacs.d/snippets/ruby-mode/yard-method-abstract に保存されます
同じようにいろいろとスニペットを作成していきます
すべて登録できたら M-x yas-describe-tables で確認しましょう

Yasnippet の自動起動

今回はモードを気にせず自動起動するようにします
必要なモードのときのみ起動するようにするには add-hook などと組み合わせてください

  • vim .emacs
; for yanippet
(require 'yasnippet)
(yas-global-mode 1)

動作確認

*.rb ファイルを開いている状態 (ruby-mode が起動している状態) で yas-insert-snippet を実行してみましょう
以下のようにちゃんと登録したスニペットの一覧が表示されて選択することで yard のドキュメントが登録できることが確認できると思います

その他操作方法

スニペットの追加

  • M-x yas-insert-snippet

スニペットの編集

  • M-x yas-visit-snippet

or

  • C-c C-v

最後に

Yasnippet を使って yard のドキュメントテンプレートを管理してみました
パッケージにして package-install でインストールできるようにしてもいいかなと思いました

参考サイト

2020年5月29日金曜日

Sinatra アプリに yard ドキュメントを付与する方法

概要

Sinatra の get などの DSL を yardoc に表示する方法を紹介します
yard-sinatra というプラグインを使います

環境

  • macOS 10.15.4
  • Ruby 2.7.1p83
    • yard-sinatra 1.0.0
    • yard 0.9.25

インストール

  • bundle init
  • vim Gemfile
gem "sinatra"
gem "yard"
gem "yard-sinatra"
  • bundle config path vendor
  • bundle install

サンプルコード

# coding: utf-8
require 'sinatra'

# 取得
get '/hoge' do
end

# 追加
post '/hoge' do
end

# パスなし
not_found do
end

# サーバエラー
error 500 do
end

# ヘルパーDSL
helpers do
  # hoge 関数
  def hoge
  end
end

ドキュメント生成

  • bundle exec yard doc --plugin yard-sinatra app.rb
  • open doc/index.html

動作確認

helperserror に関してはドキュメントが生成されないようです

に関しては helpers は module として切り出せばそちらでドキュメントを書くことができるかなと思います
error ハンドリングに関してはできればやってほしいところです

2020年5月28日木曜日

Gitlab の有償プランで発行されたライセンスーの情報を復号化してライセンスの情報を確認する方法

概要

Gitlab のライセンスの情報は管理画面に入力することで確認できます
管理画面にわざわざ入力するのが面倒な場合は gitlab-license という gem を使えば CLI などから確認できます

環境

  • macOS 10.15.4
  • Ruby 2.7.1p83
    • gitlab-license 1.0.0

準備

  • bundle init
  • vim Gemfile
gem "gitlab-license"
  • bundle config path vendor
  • bundle install

サンプルコード

  • vim app.rb
require 'base64'
require 'json'
require 'gitlab/license'
require 'openssl'

data = <<"EOF"
enter your license key
EOF

public_key_file = File.read("./.license_encryption_key.pub")
public_key = OpenSSL::PKey::RSA.new(public_key_file)
Gitlab::License.encryption_key = public_key
l = Gitlab::License.import(data)
puts l.to_json

license_encryption_key.pub は gitlab のリポジトリで公開されている公開鍵を使います

これで WebUI と同じライセンスの情報が JSON 文字列で確認できます

2020年5月27日水曜日

Ruby でメソッドの呼び出し元のファイルがどこにあるか確認する方法

概要

Method#source_location を使います 

環境

  • macOS 10.15.4
  • Ruby 2.7.1p83

サンプルコード

module A
  class B
    def hoge
      puts "hoge"
    end

    def self.fuga
      puts "fuga"
    end
  end
end

p A::B.instance_method(:hoge).source_location
p A::B.public_method(:fuga).source_location

インスタンスメソッドの場合は instance_method を使いクラスメソッドの場合は public_method を使いましょう
とりあえずクラス内にあるメソッド全部の場所を調べたい場合は以下のようにするといいでしょう

p (A::B.instance_methods + A::B.public_methods - Object.methods).map { |m| 
  begin
    A::B.instance_method(m).source_location
  rescue
    A::B.public_method(m).source_location
  end
}

参考サイト

2020年5月26日火曜日

Mac で Scratch から Minecraft を操作してみる

概要

Minecraft の forge を使うと Scratch から Minecraft を操作することができます
今回はセットアップの方法と実際にブロックの配置を Scratch から行うところまでやってみました
また Scratch は 2.0 の Flash 版だと Minecraft 連携できるのです 3.0 の Web 版だと連携できないので非公式で対応してくださっている Scratch3.0改 を使います

環境

  • macOS 10.15.4
  • Minecraft 1.15.2 (ただしゲームのバージョンは 1.12.2)
  • forge 1.12.2
    • Raspberry Jam Mod 1.12.2
  • Scratch 3.0改 (Firefox76.0.1)

Minecraft の購入とインストール

こちらの記事を参考に行ってください

Forge のインストール

こちらの記事を参考に行ってください

ただ Raspberry Jam Mod が 1.15 に対応していないので 1.12.2 という古いバージョンの Forge をインストールしてください
http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.12.2.html

Raspberry Jam Mod のインストール

こちらの記事を参考に行ってください
起動ポートはデフォルトの 4711 を使います

Minecraft の起動

forge で起動します

一応 mod が有効になっているか確認します

あとはクリエイティブモードで適当にワールドを作成しておきます

またゲームが起動したら「F3 + p」でフォーカスが外れても一時停止しないようにしておきます

Scratch3.0改の起動

https://manaviva.github.io/scratch-gui/ にアクセスします
左下の拡張機能から「Micramming」を選択します

あとは左メニューにある命令からいろいろと右ペインにドラッグアンドドロップすれば OK です

例えば自分の位置に石を置くサンプルは以下のとおりです

  • 自分の座標を調べる
  • 石を「自分のX座標」「自分のY座標」「自分のZ座標」に置く

をつなげてクリックすれば OK です
実際に動かした gif も作成したのでよければ御覧ください

最後に

Mac 上で Minecraft と Scratch の連携を行ってみました
これでプログラミングの勉強を始めるのもいいのかなと思います
Raspberry Jam Mod のバージョンがだいぶ古く最新の Minecraft のバージョンには追従できていないのが残念なところです

Java 版の場合は Forge + Raspberry Jam Mod を使えば外部の言語や WebUI と大抵は連携できます (参考: Ruby と連携する場合)

Windows であれば統合版の MakeCode for Minecraft という機能が使えるので素直にそれを使うのがいいでしょう

参考サイト

2020年5月25日月曜日

Gitlab のソースコードを最新版にしたらやるべきこと

概要

Gitlab をソースコードからインストールしている場合にリポジトリを最新にすることがあると思います
その場合にやるべきこと備忘録として残しておきます

環境

  • GitLab Enterprise Edition 13.0.0-pre 1e0d5ffbe29

ライブラリの再インストール

  • sudo su - git
  • cd gitlab
  • bundle install --with development test

assets ファイルの再生成

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

データベースのマイグレート (初期化)

  • sudo su - git
  • cd gitlab
  • DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake gitlab:setup RAILS_ENV=production

この方法はデータも全部初期化します (root のパスワードやライセンス、すべてのプロジェクト情報など)
本来は以下を実行するのが望ましいかなと思いますがエラーになってしまったので上記を実行しています

  • bundle exec rake db:migrate RAILS_ENV=production

なお gitlab:setup は postgres へのアクセスがない状態で行う必要があるので gitlab のプロセスを停止し gitaly だけ起動している状態にします

  • 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

ディレクトリ削除

DB を初期化した場合にリポジトリのディレクトリが残っているとエラーになります
データディレクトリも削除しましょう

  • REMOVE=true bundle exec rake gitlab:cleanup:moved
  • rm -rf /home/git/repositories/@hashed/

その他

本当は workhorse や gitaly をインストールする rake タスクも再度実行する必要があると思います

2020年5月24日日曜日

Gitlab の有料プランのフリートライアルに申し込んでみた

概要

Gitlab は基本無料で使えますが有料プランに申し込むことで機能の拡充ができます
今回は実際に登録する方法と登録した際に発行されるライセンスキーの登録方法を紹介します

環境

  • GitLab Enterprise Edition 13.0.0-pre

Free Trial に登録する

https://about.gitlab.com/free-trial/self-managed/ ここから登録できます
メールアドレスと名前、組織情報を簡単に入力します

ライセンスキーがメールで届く

登録したメールアドレスにライセンスキーが届きます
若干ラグがありましたが 10 分ほどでライセンスキーが到着しました

Gitlab にライセンスキーを登録する

Admin Area から登録します

左メニューのライセンスを選択します

「Upload New License」を選択します

そしてメールで届いたライセンスキーを入力します

入力したら Upload license で登録します
登録が完了するとライセンス登録時に入力した名前や組織名が確認できます

動作確認

例えば Admin Area から「Settings」->「Integrations」を見てみましょう
すると「Elasticsearch」の項目が増えておりここから Elasticsearch Integration を試すことができます

最後に

Gitlab の Free Trial を登録する方法を紹介しました
これで 30 日間は Ultimate と同じ機能を使うことができます

2020年5月23日土曜日

shallow clone したリポジトリを最新のコミットに追従させる方法

概要

git clone --depth 1 は shallow clone といい最新のコミット情報だけを取得することができます
clone 対象のリポジトリが大きいときなどに使います
ただこのリポジトリに対して git pull を行うとせっかく shallow clone したのにリポジトリ全体をダウンロードしてしまいます
今回は shallow clone したリポジトリを最新のコミットに変更する方法を紹介します

環境

  • Ubuntu 16.04 LTS
  • git 2.26.2

やり方

リモート側の origin/master の最新コミットに追従する場合は以下のようにします

  • git featch -u origin master
  • git reset --hard origin/master

これで shallow clone したリポジトリの最新コミットがリモート側と同じになります
ただし注意点としては shallow clone で depth 1 を指定しているので残るコミットは最新の 1 つになります
shallow clone した時点からのコミットが残るわけではないので注意しましょう

参考サイト

2020年5月22日金曜日

Gitlab で git lfs を使ってみた

概要

git-lfs は大きいファイルをリポジトリ以外の場所で管理することができる機能です
例えば git-lfs の対象にしたファイルを S3 などで管理することができます

Gitlab はデフォルトで git lfs が使えるようになっています
今回はクライアント側で git-lfs のインストールから実際に push して動作確認するところまでやってみました
なお今回使用する Gitlab は過去にソースコードからインストールした 13.0 のバージョンを使います

環境

  • GitLab Enterprise Edition 13.0.0-pre 52c7947911d
  • macOS 10.15.4
  • git-lfs 2.11.0

git-lfs のインストール

クライアントマシンに git-lfs をインストールします
git-lfs はリポジトリに対してクライアント側で設定します

  • brew install git-lfs

適当にリポジトリを clone

  • git clone http://gitlab.example.com/root/test.git

リポジトリで git lfs を有効にする

git-lfs を使いたい場合は必ず install する必要があります

  • cd test
  • git lfs install

サイズの大きいファイルを作成して push してみる

今回は 1GB のファイルを作成します
大きいサイズのファイルがあればそれを使っても OK です

  • dd if=/dev/zero of=test_file bs=1024k count=1000
  • git lfs track "test_file"

作成した test_file を git-lfs の対象にします
git lfs track すると .gitattributes も同時に作成できるのでこれも追加します

  • git add .

ちなみに git lfs status すると対象のファイルを確認できます

On branch master Objects to be pushed to origin/master:   Objects to be committed:   .gitattributes (Git: 5c5b0b5) my_file (LFS: da87281)   Objects not staged for commit:
  • git config lfs.http://gitlab.example.com/root/test.git/info/lfs.locksverify true
  • git commit -m "git-lfs test"
  • git push -u origin master

動作確認

まず Gitlab の WebUI を確認すると対象のファイルが git-lfs 配下で管理されていることが確認できます

次に新たに clone してみます
すると 2 回認証することになると思います
2 回目は git-lfs の認証になるのでそれに成功すると git-lfs の対象のファイルを clone することができます

S3 などにする場合は

デフォルトだと localhost の /home/git/gitlab/shared/lfs-objects というパスで管理されています
パスを変更したり S3 にしたい場合は gitlab/config/gitlab.ymllfs の項目を変更してプロセスを再起動すれば OK です

トラブルシューティング

push 時に HTTP 413 になる場合

/etc/nginx/sites-available/gitlab の設定は Gitlab 13.0 では デフォルトで client_max_body_size 0 になっています
git config lfs.http://gitlab.example.com/root/test.git/info/lfs.locksverify true を実行した際にホスト名などが間違っていないか確認しましょう

あとは push する際のパスワードがあっているか確認しましょう
Gitlab の WebUI にログインする際のパスワードではなく Access Token などを使ってみてください
https://gitlab.com/gitlab-com/support-forum/-/issues/980

もしくは git config の remote の URL を http://gitlab.example.com/root/test.git から http://root:xxxxxx@gitlab.example.com/root/test.git という感じでユーザ名とパスワードを指定するようにしてください

あとは単純にディスクのスペースが空いているか確認しましょう
/var/log/nginx/gitlab_error.log あたりのログに No space left on device というエラーログが出ている場合があります

パスワードを 3 回求めてくる場合は

  • git config lfs.cachecredentials true

最後に

Gitlab で git-lfs を使ってみました
Gitlab 側はデフォルトで有効になっているであとはクライアント側で設定するだけですが Gitlab の場合認証部分で少してこづるかもしれません
特に 413 エラーは検索してみるとわかりますが多くの人が遭遇しているエラーかなと思いました

参考サイト

2020年5月21日木曜日

GarageBand で録音した音にプツプツ音が含まれている原因と対策

概要

GarageBand で録音した音にプツプツという音が入っていました
波形がスパイクしている場合は良いのですが特にスパイクもなくプツプツしている場合の原因と対策を紹介します

原因

おそらくですが録音環境が悪いのが原因です
マイクとマシンとの接続が不良であったりマシンのスペックが低いため録音がミスしているのが原因かと思われます
もしくは GarageBand 自体がおかしい可能性もあるので別の録音ソフトを使っても良いかなと思います

現象

波形と途中で切れているようになっているためです (画像は録音した音源を Audacity で編集中の画面)

このような波形がある場合はスパイクしていないにも関わらずプツプツという雑音が入ってしまいます

対策

波形がない部分を選択します

そして Delete キーを押して削除します

あとは「エフェクト」->「修復」ツールを使って削除した波形の左右を滑らかにします

とりあえずこれでプツプツは解消されるはずです

問題点

今回 Audacity を使って対応しました
Audacity の「修復」ツールは非常に小さな範囲しか適用できません
なのでプツプツ音が大量のある音源の場合には非常に大変な作業になります
今回の波形の場合「ノイズの低減」や「ノッチフィルタ」では対応できませんでした

もしくは有料ですが RX という編集ツールの Discontinuity という機能を使えば波形が連続していない部分を検出してくれるようなので楽に編集できるかもしれません (未検証)

2020年5月20日水曜日

Slack のメッセージをすべて削除する方法

概要

Slack の general チャネルにあるメッセージをすべて削除する方法を紹介します
今回紹介する方法は slack-cleaner というツールを使います

環境

  • Python 3.7.3
    • pip 20.0.2
  • slack-cleaner 0.7.3

slack-cleaner のインストール

  • pip3 install slack-cleaner

slack-cleaner コマンドが実行できない場合は再ログインするか新たにターミナルを開いてください

削除実行

  • slack-cleaner --token <TOKEN> --message --channel general --user "*"

でドライランで削除するメッセージの数と内容を確認します
--perform を付与することで実際に削除します
大量にメッセージがある場合は削除に多少時間がかかるので待ちましょう

  • slack-cleaner --token <TOKEN> --message --channel general --user "*" --perform

ボットや Incomming Web hook からのメッセージを削除する方法

--bot を指定します

  • slack-cleaner --token <TOKEN> --message --channel general --bot "*" --perform

TOKEN の取得方法

今回はレガシートークンを使用しました
https://api.slack.com/legacy/custom-integrations/legacy-tokens

本来であれば OAuth2 アプリを作成してトークンを取得してから実行する必要があります

2020年5月19日火曜日

Finder で新規タブを開いた際のデフォルトディレクトリを指定する方法

環境

  • macOS 10.15.4

やり方

Finder の Preferences を開いて「新規Finderウインドウで次を表示」で好きなディレクトリを選択すれば OK です

2020年5月18日月曜日

Gitlab をソースコードからインストールしてみた (master ブランチ編)

概要

前回 11.8-stable ブランチのソースコードを clone してソースコードからインストールしてみました
今回は master ブランチを clone してビルドしてみます
基本的には前回と同じなので前回と違う手順だけ紹介します

環境

  • GitLab Enterprise Edition 13.0.0-pre 52c7947911d
  • Ruby 2.6.5 (rvm)
  • Golang 14.2
  • それ以外は前回と同じ

rack_attack.rb.example がなくなっていた

rack_attack_new.rbrack_attack_logging.rb がすでに配置されているので特にサンプルからコピーする作業がなくなりました

native extension をビルドするために必要なパッケージが増えた

  • sudo apt -y install libicu-dev cmake libkrb5-dev libre2-dev

clone するリポジトリが異なる

foss ではなく gitlab 本体を clone しましょう
またブランチも指定しません

  • git clone --depth 1 https://gitlab.com/gitlab-org/gitlab.git gitlab

unicorn.rb -> puma.rb になっている

Web サーバが unicorn から puma になっているので配置する設定ファイルも puma.rb を配置します

  • cd /home/git/gitlab
  • cp config/puma.rb.example config/puma.rb

systemctl start gitlab 起動しない

エラー分は「Cannot allocate memory - daemon (Errno::ENOMEM)」でした
愚直に vagrant のメモリサイズを 4GB -> 6GB にしたところうまく起動しました

config.vm.provider "virtualbox" do |vb|
  vb.memory = 6144
  vb.cpus = 2
end

基本的には /etc/init.d/gitlab start で手動実行してログを確認しながらトラブルシューティングしてみましょう

起動はしているが systemctl のステータスは failed になってしまう

起動スクリプトの pid ファイルをチェックする部分がおかしいようです
問題なく動作しているのに exit 1 しているためです

  • sudo vim /etc/init.d/gitlab
wait_for_pids(){
  i=0;
  while [ ! -f $web_server_pid_path ] || [ ! -f $sidekiq_pid_path ] || [ ! -f $gitlab_workhorse_pid_path ] || { [ "$mail_room_enabled" = true ] && [ ! -f $mail_room_pid_path ]; } || { [ "$gitlab_pages_enabled" = true ] && [ ! -f $gitlab_pages_pid_path ]; } || { [ "$gitaly_enabled" = true ] && [ ! -f $gitaly_pid_path ]; }; do
    sleep 0.1;
    i=$((i+1))
    if [ $((i%10)) = 0 ]; then
      echo -n "."
      break;
    elif [ $((i)) = 301 ]; then
      echo "Waited 30s for the processes to write their pids, something probably went wrong."
      exit 1;
    fi
  done
  echo
}

これでステータスが正常で終了します

最後に

Gitlab のインストールをソースコードから行ってみました
基本的には前回と同じでしたが使用している gem が増えていたりしていたので必要なパッケージが増えていたり puma が標準になっていたりとやや違いがありました
メジャーバージョンアップするごとに毎回ビルドを試してみても良いかもしれません
おそらくバージョンアップするたびにエラーになるような気がします

2020年5月17日日曜日

puma 最速入門 (Sinatra編)

概要

puma/puma は簡単に言えば Ruby で Web アプリケーションを動作させるための Web Server です
単体では Web アプリケーションとして動作せず Rails や Sinatra と組み合わせて使います
今回は Sinatra と組み合わせて使い方を紹介します

環境

  • Ruby 2.7.1p83
  • Sinatra 2.0.8.1
  • puma 4.3.3

インストール

  • bundle init
  • vim Gemfile
gem "puma"
gem "sinatra"
  • bundle config path vendor
  • bundle install

とりあえず動かしてみる

Sinatra は puma がインストールされている場合は WEBrick ではなく puma を優先的に使います
なので特に何も記載することなく自動的に puma を使ってくれます

  • vim config.ru
require './app.rb'
run WebApp
  • vim app.rb
require 'sinatra/base'

class WebApp < Sinatra::Base
  get '/' do
    'ok'
  end
end

これで起動すると自動的に puma で Sinatra が起動します

  • bundle exec rackup config.ru
Puma starting in single mode… * Version 4.3.3 (ruby 2.7.1-p83), codename: Mysterious Traveller * Min threads: 0, max threads: 16 * Environment: development * Listening on tcp://127.0.0.1:9292 * Listening on tcp://[::1]:9292 Use Ctrl-C to stop

config/puma.rb を書いて puma をチューニングする

puma は config/puma.rb を記載することで自分でいろいろとカスタマイズすることができます
例えば以下のように記載することで 3 つのワーカープロセスが動作することで cluster mode として動作させることができます

  • vim config/puma.rb
workers 3
preload_app!
  • bundle exec rackup config.ru
[23514] Puma starting in cluster mode… [23514] * Version 4.3.3 (ruby 2.7.1-p83), codename: Mysterious Traveller [23514] * Min threads: 0, max threads: 16 [23514] * Environment: development [23514] * Process workers: 3 [23514] * Preloading application [23514] * Listening on tcp://127.0.0.1:9292 [23514] Use Ctrl-C to stop [23514] - Worker 0 (pid: 23515) booted, phase: 0 [23514] - Worker 1 (pid: 23516) booted, phase: 0 [23514] - Worker 2 (pid: 23517) booted, phase: 0

確かに先ほどと違って worker プロセスが 3 つほど起動しているのがわかります
マシンリソースとの相談ですが worker プロセスの数を増やすことで多くのリクエストを並列にさばくことができます

worker が起動する際に何か処理をさせたい場合

on_worker_boot を定義することでワーカー起動時に何かしら処理をさせることができます
基本的には初期化処理になるのでロギングの設定やコネクションチェックなど行うと良いと思います

  • vim config/puma.rb
workers 3
preload_app!

on_worker_boot do
  puts 'Before worker fork...'
end
  • bundle exec rackup config.ru
[23584] Puma starting in cluster mode… [23584] * Version 4.3.3 (ruby 2.7.1-p83), codename: Mysterious Traveller [23584] * Min threads: 0, max threads: 16 [23584] * Environment: development [23584] * Process workers: 3 [23584] * Preloading application [23584] * Listening on tcp://127.0.0.1:9292 [23584] Use Ctrl-C to stop Before worker fork… Before worker fork… [23584] - Worker 0 (pid: 23585) booted, phase: 0 Before worker fork… [23584] - Worker 1 (pid: 23586) booted, phase: 0 [23584] - Worker 2 (pid: 23587) booted, phase: 0 ^C[23584] - Gracefully shutting down workers… [23584] === puma shutdown: 2020-05-15 09:33:47 +0900 === [23584] - Goodbye!

ちなみに定義できるハンドラは dsl.rb で確認できます

起動するポートを変更する

port を使います

  • vim config/puma.rb
workers 3
preload_app!

on_worker_boot do
  puts 'Before worker fork...'
end

port 9999

などなどいろいろ設定できるので dsl.rb を確認してみてください

最後に

Sinatra を使って puma のチューニング方法を簡単に紹介しました
プロファイリングや負荷テストなどしながらやるとベストな設定が見つけられると思います
リバースプロキシなどを挟んでいる場合はそちらのチューニングも見る必要があるので注意しましょう
基本的にはリバースプロキシが捌けるであろうリクエスト数よりも puma のほうが多くリクエストを捌ける必要があると思います

参考サイト

2020年5月16日土曜日

Gitlab で Gitaly だけを外部のサーバに移行する方法

概要

Gitaly は gitlab 内で動作しているプロセスで git リポジトリに gRPC プロトコルでアクセスできるようになる gitlab のコンポーネントです
Omnibus Install された gitlab の場合は基本的には gitlab-rails のアプリケーションと同じ VM 内で動作しています
しかし git リポジトリが大きくなりスケールさせる必要がある場合には別 VM に移行することができます
今回は Gitaly だけを外部の VM に移行する方法を紹介します

Gitaly のインストール (Omnibus GitLab のインストールを使う)

まずは普通に Omnibus Install で Gitlab をインストールします
注意するのはインストールの際に指定する EXTERNAL_URL を指定しないことです

  • sudo apt -y update
  • sudo apt install -y curl openssh-server ca-certificates
  • curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
  • sudo apt -y install gitlab-ee

gitlab.rb を編集して gitaly だけを起動するようにする

Omnibus Install で起動するプロセスを gitaly だけにします

  • sudo su -
  • mv /etc/gitlab/gitlab.rb{,.back}

まずは各プロセスを起動しないように設定します
また Gitaly をリモートからでもアクセスできるように LISTEN させます

  • touch /etc/gitlab/gitlab.rb
  • vim /etc/gitlab/gitlab.rb
postgresql['enable'] = false
redis['enable'] = false
nginx['enable'] = false
unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
grafana['enable'] = false
alertmanager['enable'] = false
prometheus['enable'] = false
gitlab_rails['rake_cache_clear'] = false
gitlab_rails['auto_migrate'] = false
gitlab_rails['internal_api_url'] = 'http://gitlab.example.com'
gitaly['auth_token'] = 'abc123secret'
gitaly['listen_addr'] = "0.0.0.0:8075"

internal_api_url は http を指定しましょう
また auth_token は好きな文字列で OK です
次に gitaly が管理する git リポジトリを指定します

  • vim /etc/gitlab/gitlab.rb
git_data_dirs({
  'default' => {
    'path' => '/var/opt/gitlab/git-data'
  },
  'storage1' => {
    'path' => '/mnt/gitlab/git-data'
  },
})
  • mkdir -p /mnt/gitlab/git-data

あとは reconfigure を実行します

  • gitlab-ctl reconfigure

プロセスを確認すると gitaly とその他メトリックを取得するためのプロセスのみが動作しているのが確認できると思います

  • gitlab-ctl status
run: gitaly: (pid 3010) 501s; run: log: (pid 2812) 520s
run: gitlab-exporter: (pid 2996) 502s; run: log: (pid 2995) 502s
run: logrotate: (pid 2902) 515s; run: log: (pid 2926) 514s
run: node-exporter: (pid 2985) 502s; run: log: (pid 2942) 508s

/etc/hosts に gitlab の FQDN を解決できるように登録しておく

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

gitlab 本体で外部の gitaly を参照するようにする

あとは gitlab 本体で構築した外部の gitaly を参照させます
この作業は gitaly サーバではなく gitlab 本体のサーバで行います

  • sudo vim /etc/gitlab/gitlab.rb
git_data_dirs({
  'default' => { 'gitaly_address' => 'tcp://192.168.100.13:8075' },                                                              
  'storage1' => { 'gitaly_address' => 'tcp://192.168.100.13:8075' },                                                             
})

gitlab_rails['gitaly_token'] = 'abc123secret'

これで reconfigure -> start しましょう

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

/etc/gitlab/gitlab-secrets.json を gitlab 本体からコピーする

gitaly サーバに gitlab 本体側からコピーしてきます
コピペでも何でも OK です
これがないと push 時にエラーになります

  • sudo su -
  • mv /etc/gitlab/gitlab-secrets.json{,.back}
  • scp gitlab.example.com:/etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json

コピー後は gitaly 側で reconfigure が必要になるので実行します

  • gitlab-ctl reconfigure

動作確認

あとは実際にプロジェクトを作成して外部の gitaly 側にデータが格納されているか確認します

適当にプロジェクトを作成し git clone してみましょう
そして add -> commit -> push して gitaly 側の git_data_dirs を確認してみましょう

  • ls /var/opt/gitlab/git-data/repositories/ /mnt/gitlab/git-data/repositories/
/mnt/gitlab/git-data/repositories/:
+gitaly

/var/opt/gitlab/git-data/repositories/:
+gitaly  @hashed

こんな感じで default 側に @hashed というディレクトリができていれば OK です

トラブルシューティング

gitlab 本体でエラーを確認する場合は/var/log/gitlab/gitlab-rails あたりを確認しましょう

gitaly 側で確認するログは /var/log/gitlab/gitaly/current になります

マイグレーションできるのか

ちなみに自分が試したときはすでにプロジェクトがある状態でした

  • 1 つ以上の git push をしているプロジェクト
  • まだ 1 つも git push していないプロジェクト

これらのプロジェクトがある状態で外部の gitaly を参照するようにした場合は前者はプロジェクトにアクセスすると 404 になり後者はアクセスしてもエラーにはなりませんでした
理由としては簡単で push 済みの前者のプロジェクトは外部の gitaly にリポジトリのデータがないので 404 エラーになっているかなと思います
また後者は push していないのでまだ git リポジトリが作れていないのでエラーになりません
ただ clone しようとした場合両者とも fatal: the remote end hung up unexpectedly になりました

これを踏まえて両者のプロジェクトが外部の gitaly に移行してもエラーにならないようにする必要があるかなと思います
おそらく単純なファイルなのでそれを移動すれば直るはずですが試していないので何とも言えません
一番手っ取り早く解消するのは gitlab 本体側の git_data_dirs に外部以外のローカルのパスも書いておくことだと思います

gitlab 本体側

git_data_dirs({
  'default' => { 'path' => '/var/opt/gitlab/git-data' },
  'storage1' => { 'gitaly_address' => 'tcp://192.168.100.13:8075' },
  'storage2' => { 'gitaly_address' => 'tcp://192.168.100.13:8075' },
})

gitaly 側

git_data_dirs({
  'storage1' => {
    'path' => '/var/opt/gitlab/git-data'
  },
  'storage2' => {
    'path' => '/mnt/gitlab/git-data'
  },
})

これだと WebUI も git clone もエラーにならず既存のプロジェクトも動作します
が gitlab 本体側に相変わらず git のデータが配置されてしまうので微妙な感じになってしまいます

default と storage1, storage2 がどう使われるか不明

おそらく gitaly が良い感じに振り分けてくれるのだと思います
ただ続けてプロジェクトを作った場合に全部 default 側に作成されました
ストレージの容量などを見て分散してくれる感じなのでしょうか
どこかドキュメントを探すかコードをみればわかるかなと思います

最後に

Gitlab を構成するコンポーネントの 1 つである Gitaly を外部の VM に移行する方法を紹介しました
これで単純に git リポジトリの分散はできるようになります
Gitaly がダウンすると WebUI も git リポジトリのアクセスもできなくなります
そのため Praefect という HA 機構もありこれを使うことで更に堅牢な Gitlab を構築することができます

参考サイト

2020年5月15日金曜日

Omnibus Install した Gitlab で Grafana Dashboard にアクセスする方法

概要

Omnibus Install した Gitlab であればデフォルトで使えるようになっています

環境

  • GitLab Enterprise Edition 12.9.2-ee

URL

http://gitlab.example.com/-/grafana/login でアクセスできます
ID/PW は Gitlab に登録したアカウントで行えます

「Sign in with Gitlab」をクリックすれば Gitlab のアカウントで認証できます

「Gitlab Omnibus - Overview」あたりを選択すればこんな感じでメトリックを確認することができます

トラブルシューティング

The redirect URI included is not valid.

「Sign in with Gitlab」でログインした際に発生することがあります
これは Gitlab 側の callback URL が正しく設定されていないときに出るようです

「Admin Area」->「Applications」->「Gitlab Grafana」->「Edit」で URL が正しいか確認します

自分は Callback URL が https だったのを http に変更したらうまく動作しました

login.OAuthLogin(missing saved state)

Grafana 側でエラーになる場合もあるようです

Grafana サーバが動作しているマシンで gitlab.example.com の FQDN が名前解決できていないために発生します

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

こんな感じで名前解決できるようにしてあげれば OK です

最後に

Gitlab で Grafana Dashboard を確認する方法を紹介しました
結構便利ですが管理者以外も URL がわかればアクセスできてしまうので認証は Gitlab 認証を使わないほうが良いかもしれません

参考サイト

2020年5月14日木曜日

Gitlab で ssh clone する方法

概要

事前に clone するユーザの公開鍵を gitlab に登録する必要があります

環境

  • macOS 10.15.4
  • GitLab Enterprise Edition 12.9.2-ee

鍵の作成

  • ssh-keygen -t rsa

id_rsa.pub を Gitlab に登録する

  • cat ~/.ssh/id_rsa.pub

の情報を Gitlab のアカウントの Settings から「SSH Keys」に登録します

clone する

  • git clone git@gitlab.example.com:root/test.git

2020年5月13日水曜日

Gitlab Development Kit を使って Gitlab をソースコードインストールしたみた

概要

Gitlab Development Kit を使って Gitlab のインストールをソースコードから行ってみました
GDK を使わず直接ソースコードからインストールする方法も過去に紹介しています

以下の作業は Vagrant 上に構築した Ubuntu 上で実行しています
またユーザは vagrant ユーザで行います

環境

  • Ubuntu 16.04 LTS
  • Ruby 2.6.5 (rvm)
  • Go 1.14.2
  • Nodejs 12.16.2
    • yarn 1.22.4
  • Postgres 9.5.21
  • Gitlab Development Kit 0.2.5

Ruby のインストール

  • sudo apt -y install gnupg2
  • gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
  • \curl -sSL https://get.rvm.io | bash -s stable

再ログインする

  • rvm install ruby-2.6.5
  • rvm alias create default ruby-2.6.5

Golang のインストール

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

Nodejs のインストール

  • 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

Postgresql のインストール

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

Redis のインストール

  • sudo apt -y install redis-server

GraphicsMagick のインストール

  • sudo apt -y install graphicsmagick

Exiftool のインストール

  • sudo apt -y install exiftool

Runit のインストール

  • sudo apt -y install runit

MinIO のインストール

  • mkdir /tmp/minio && cd /tmp/minio
  • wget https://dl.min.io/server/minio/release/linux-amd64/minio
  • chmod +x minio
  • sudo mv minio /usr/local/bin

gdk のインストール

  • gem install gitlab-development-kit

その他 native extension のインストールに必要なパッケージのインストール

  • sudo apt -y install libicu-dev cmake libkrb5-dev libre2-dev

gdk で gitlab をインストール

  • cd
  • gdk init
  • cd gitlab-development-kit
  • gdk install shallow_clone=true

gitlab 本体のリポジトリの clone が始まります
リポジトリがかなり大きいので shallow clone にします
内部的には Makefile に記載の内容を実行している感じです
ruby, node, go で各アプリケーションのビルドとインストールを行います
また開発に必要なサンプルデータの投入も Postgres に行ってくれます
「Setup finished!」が表示され Gitlab の AA が表示されれば完了です

動作確認

各種プロセスの状態を確認します

  • gdk status
down: ./services/gitlab-pages: 789s; run: log: (pid 8866) 789s
down: ./services/gitlab-workhorse: 789s; run: log: (pid 8868) 789s
down: ./services/jaeger: 789s; run: log: (pid 8864) 789s
run: ./services/postgresql: (pid 8878) 789s, normally down; run: log: (pid 8871) 789s
run: ./services/praefect: (pid 8877) 789s, normally down; run: log: (pid 8863) 789s
run: ./services/praefect-gitaly-0: (pid 8876) 789s, normally down; run: log: (pid 8865) 789s
down: ./services/rails-actioncable: 789s; run: log: (pid 8870) 789s
down: ./services/rails-background-jobs: 789s; run: log: (pid 8873) 789s
down: ./services/rails-web: 789s; run: log: (pid 8867) 789s
run: ./services/redis: (pid 9437) 678s, normally down; run: log: (pid 8869) 789s
down: ./services/webpack: 789s; run: log: (pid 8872) 789s

初回設定で必要だったプロセスのみ起動しているようです
では各種プロセスを起動して Gitlab にアクセスできるか確認します

  • gdk start
run: ./services/gitlab-pages: (pid 3501) 223s, normally down; run: log: (pid 3485) 227s
run: ./services/gitlab-workhorse: (pid 3499) 223s, normally down; run: log: (pid 3488) 227s
run: ./services/jaeger: (pid 3500) 223s, normally down; run: log: (pid 3486) 227s
run: ./services/postgresql: (pid 3503) 223s, normally down; run: log: (pid 3487) 227s
run: ./services/praefect: (pid 3502) 223s, normally down; run: log: (pid 3478) 227s
run: ./services/praefect-gitaly-0: (pid 3504) 223s, normally down; run: log: (pid 3481) 227s
run: ./services/rails-actioncable: (pid 3509) 223s, normally down; run: log: (pid 3483) 227s
run: ./services/rails-background-jobs: (pid 3505) 223s, normally down; run: log: (pid 3480) 227s
run: ./services/rails-web: (pid 3506) 223s, normally down; run: log: (pid 3479) 227s
run: ./services/redis: (pid 3507) 223s, normally down; run: log: (pid 3484) 227s
run: ./services/webpack: (pid 3508) 223s, normally down; run: log: (pid 3482) 227s

すべてのプロセスが run になっていれば OK です
これで localhost:3000 で起動しています
もし localhost 以外からアクセスする場合は gdk.yml の設定を変更しましょう

  • vim gdk.yml
hostname: 192.168.100.12`

これで reconfigure すれば OK です

  • gdk reconfigure

これで http://192.168.100.12:3000 などの IP にアクセスすれば OK です
ログインは root/5iveL!fe でできます
502 になる場合はしばらくしてからアクセスしてください

最後に

GDK を使って gitlab をソースコードからインストールして各種コンポーネントが開発できる環境を作ってみました
バージョンなどの指定があるのでそこは注意しましょう
また root ユーザで作業しないのもポイントで psql の操作をするときに root ユーザだとエラーになるので注意しましょう

公式のドキュメントだと手順が足りないのでトライ&エラーで何度も試しながらやりました

GDK を使わず直接ソースコードからインストールする方法に比べて必要なデータが揃っているので開発はしやすいかもしれません
ただ 1 つの VM 内でたくさんのプロセスが動作するので快適に開発するのであれば 4vCPU/8GB くらいのスペックの VM が必要になりそうでした

参考サイト

2020年5月11日月曜日

WKWebView で UserAgent を設定する方法

概要

WKWebView で既存の UserAgent を取得してそれを書き換えて UserAgent を変更する方法を紹介します

環境

  • macOS 10.15.4
  • Xcode 11.4.1 (11E503a)

サンプルコード

WKWebView は WebKit が必要になるので最初に import します

import WebKit

あとは WKWebView を作成して UserAgent を設定します
既存の UserAgent を取得するには evaluateJavaScript を使って JavaScript を発行し内部のブラウザから UserAgent の情報を取得します
あとは取得した文字列情報の UserAgent を replace などを使って書き換えます

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  var webView: WKWebView? = WKWebView()
  webView!.evaluateJavaScript("navigator.userAgent", completionHandler: { (result, error) in
      webView = nil
      guard let ua = result as? String else {
          return
      }
      let customUserAgent = ua.replacingOccurrences(of: "iPad", with: "iPhone")
      let dic: NSDictionary = ["UserAgent" : customUserAgent]
      UserDefaults.standard.register(defaults: dic as! [String : AnyObject])
  })
}

上記は iPad 用の UserAgent を iPhone の UserAgent に書き換えています

UserAgent の情報は UserDefaults.standard.register を使って登録します
この方法にすることでアプリ全体で使用する UserAgent を設定することになるので再度設定の必要がなくなります
なので実行する場合は didFinishLaunchingWithOptions など初期化の際に一度だけ実行されるメソッド内で行うとよいでしょう

逆に毎回 UserAgent を変更したい場合は WKWebView.customUserAgent を使ってください

2020年5月7日木曜日

Ruby2.7 + cocoapods1.9.1 で JSON::ParserError になる場合の対処方法

概要

エラーの一部ですが JSON::ParserError - 783: unexpected token at '' というエラーが出ます
対応策を紹介します

環境

  • macOS 10.15.4
  • Ruby 2.7.1p83
  • cocoapods 1.9.1

対応策

どうやらバージョン互換がないようで古いバージョンからの pod update だとエラーになるようです
公式の issue にもありますがどうやら再インストールが必要なそうです

  • gem uninstall cocoapods
  • rm -rf ~/.cocoapods
  • gem install cocoapods
  • cd /path/to/your-project
  • mv Podfile{,.back}
  • mv Podfile.lock{,.back}
  • pod repo remove trunk
  • pod init
  • vim Podfile

でバックアップした Podfile の内容を書きます

  • pod install