Rubyと筋肉とギターとわたし

筋トレが仕事です

【docker】gcloud auth configure-dockerを行うとdocker buildができなくなる

どうもてぃ。

前回の記事でgcloudコマンドをPython3.8に対応させました。

smot93516.hatenablog.jp

今回の問題は、GCRへイメージをpushするためgcloud auth configure-dockerで認証を行った後に起こったことです。

調査から解決まで一連の流れを書いていこうと思います。

環境

言語関係のバージョン管理はasdfを使用しています。

% cat /etc/lsb-release 
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=19.3
DISTRIB_CODENAME=tricia
DISTRIB_DESCRIPTION="Linux Mint 19.3 Tricia"

% docker-compose -v
docker-compose version 1.27.4, build 40524192

% docker -v
Docker version 19.03.6, build 369ce74a3c

エラー内容

% docker-compose build
postgres uses an image, skipping
redis uses an image, skipping
Building web

ERROR: gcloud failed to load: /tmp/_MEIKPCrAH/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by /home/motty/.asdf/installs/python/3.8.1/lib/python3.8/lib-dynload/_ssl.cpython-38-x86_64-linux-gnu.so)
    gcloud_main = _import_gcloud_main()
    import googlecloudsdk.gcloud_main
    from googlecloudsdk.api_lib.iamcredentials import util as iamcred_util
    from googlecloudsdk.api_lib.util import apis_internal
    from googlecloudsdk.core import properties
    from googlecloudsdk.core import config
    from oauth2client import client
    from oauth2client import transport
    import httplib2
    from httplib2.python3.httplib2 import *
    import ssl
    import _ssl             # if we can't import it, let the error propagate

This usually indicates corruption in your gcloud installation or problems with your Python interpreter.

Please verify that the following is the path to a working Python 2.7 or 3.5+ executable:
    /home/motty/.asdf/installs/python/3.8.1/bin/python3

If it is not, please set the CLOUDSDK_PYTHON environment variable to point to a working Python 2.7 or 3.5+ executable.

If you are still experiencing problems, please reinstall the Cloud SDK using the instructions here:
    https://cloud.google.com/sdk/
Traceback (most recent call last):
  File "docker/credentials/store.py", line 80, in _execute
  File "subprocess.py", line 411, in check_output
  File "subprocess.py", line 512, in run
subprocess.CalledProcessError: Command '['/usr/bin/docker-credential-gcloud', 'get']' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "docker/auth.py", line 264, in _resolve_authconfig_credstore
  File "docker/credentials/store.py", line 35, in get
  File "docker/credentials/store.py", line 93, in _execute
docker.credentials.errors.StoreError: Credentials store docker-credential-gcloud exited with "".

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "bin/docker-compose", line 3, in <module>
  File "compose/cli/main.py", line 67, in main
  File "compose/cli/main.py", line 126, in perform_command
  File "compose/cli/main.py", line 302, in build
  File "compose/project.py", line 468, in build
  File "compose/project.py", line 450, in build_service
  File "compose/service.py", line 1125, in build
  File "docker/api/build.py", line 261, in build
  File "docker/api/build.py", line 308, in _set_auth_headers
  File "docker/auth.py", line 311, in get_all_credentials
  File "docker/auth.py", line 281, in _resolve_authconfig_credstore
docker.errors.DockerException: Credentials store error: StoreError('Credentials store docker-credential-gcloud exited with "".')
[29221] Failed to execute script docker-compose

暫定的な解決策

GCRへイメージをあげるのはある程度期間が空くため、暫定的にgcloud auth configure-dockerした際$HOME/.docker/config.jsonに追記される部分を削除すればdocker buildは上手く行きます。

・
・
・
  },
  "HttpHeaders": {
    "User-Agent": "Docker-Client/19.03.6 (linux)"
  },
  "credHelpers": {
    "gcr.io": "gcloud",
    "us.gcr.io": "gcloud",
    "eu.gcr.io": "gcloud",
    "asia.gcr.io": "gcloud",
    "staging-k8s.gcr.io": "gcloud",
    "marketplace.gcr.io": "gcloud"
  }
}

credHelpers部分を削除します。これで一時的に解決できます。

この部分はgcloud auth configure-dockerを実行すれば再度同じものが追記されるので安心して下さい。

根本的な解決策

おそらくOSXwindowsユーザーは起きてないのではないかと思います。

自分の環境がUbuntuのため同じような現象に悩む人がいたようです。issueがありました。

github.com

要約すると...

  • gcloudのバージョンを297.0.1にダウングレードする
  • 環境変数CLOUDSDK_PYTHONを設定する
  • LD_LIBRARY_PATHを/usr/local/libに設定する

この三点です。

手順を下に記載します。

% sudo apt install google-cloud-sdk=297.0.1-0

% which python
# => /home/motty/.asdf/shims/python

% export CLOUDSDK_PYTHON=/home/motty/.asdf/shims/python

% export LD_LIBRARY_PATH=/usr/local/lib

これで無事docker buildが通るようになりました。

終わり

やったね。

追記

解決したかと思いきや、今の所ランダムで起きてます…どうしたらいいんだこれ…

何か解決策が出てきたらまた記事にしたいと思います。

てなわけで買って下さい。超おすすめの本たちです。 ↓

【gcloud】Python3.8に対応したgcloudコマンドをインストールしたい

どうもてぃ。

久々にブログ書きます。

以前インストールしたgcloudコマンドがpython 2.7に依存するもので、gcloudコマンドを使用するたび毎回pythonのバージョンを切り替えるのクソだるかったためバージョンアップしました。

環境

% lsb_release -a
No LSB modules are available.
Distributor ID: LinuxMint
Description:    Linux Mint 19.3 Tricia
Release:    19.3
Codename:   tricia

% python -V
Python 3.8.1

やったこと

とりあえず公式にのっとって再インストールする

cloud.google.com

初期化

インストールが一通り終わったのでgcloud init

% gcloud init
ERROR: gcloud failed to load: No module named '_sqlite3'
    gcloud_main = _import_gcloud_main()
    import googlecloudsdk.gcloud_main
    from googlecloudsdk.calliope import cli
    from googlecloudsdk.calliope import backend
    from googlecloudsdk.calliope import parser_extensions
    from googlecloudsdk.core.updater import update_manager
    from googlecloudsdk.core.updater import installers
    from googlecloudsdk.core.credentials import store
    from googlecloudsdk.core.credentials import creds as c_creds
    import sqlite3
    from sqlite3.dbapi2 import *
    from _sqlite3 import *

This usually indicates corruption in your gcloud installation or problems with your Python interpreter.

Please verify that the following is the path to a working Python 2.7 or 3.5+ executable:
    /home/motty/.asdf/installs/python/3.8.1/bin/python3

If it is not, please set the CLOUDSDK_PYTHON environment variable to point to a working Python 2.7 or 3.5+ executable.

If you are still experiencing problems, please reinstall the Cloud SDK using the instructions here:
    https://cloud.google.com/sdk/
~ 

ぱっとみsqlite3が入ってないから起こってるっぽい。

対応

確かpythonはその時の状態でビルドされるため、aptsqlite関連のパッケージをインストールしたとしてもpython自体に反映されないはず。

なので、念の為aptで入れた後、pythonをインストールし直す。

ちなみに自分は言語系はasdfで管理しています。

% sudo apt-get install libsqlite3-dev libbz2-dev libncurses5-dev libgdbm-dev liblzma-dev libssl-dev tcl-dev tk-dev libreadline-dev

% asdf uninstall python 3.8.1

% asdf install python 3.8.1

かんりょぉぉおおおおおおおおおおおおお

うまくいったぜ

% gcloud init

Welcome! This command will take you through the configuration of gcloud.

Settings from your current configuration [default] are:
core:
  account: hogehogehogehoge@hoge.com
  disable_usage_reporting: 'True'
  project: hogehogehoge

Pick configuration to use:
 [1] Re-initialize this configuration [default] with new settings 
 [2] Create a new configuration
Please enter your numeric choice:  

pythonのエラー関連は割りかしハマりますね。

とりあえずgcloudコマンドがアップグレード出来てよかった。

【備忘録】docker images noneなイメージを全て削除したい

f:id:rdwbocungelt5:20180816164743p:plain

TL;DR

% docker images | grep none | xargs docker rmi `awk '{ print $3 }'`

conflictが起きて削除できないとき

Error response from daemon: conflict: unable to delete 78ef4af0ce83 (must be forced) - image is referenced in multiple repositories

上みたいなエラーが出たときは、-fで強制的に削除してやりましょう

% docker images | grep none | xargs docker rmi -f `awk '{ print $3 }'`

【Vim】raills(ruby)でvim-lspを導入するとnokogiriで怒られる

f:id:rdwbocungelt5:20200320131618p:plain

どうもてぃ。

最近vimneocompleteneocomplcacheのサポートが終わってることを知り、ちょうどいい機会だったのでlspに移行しようとした際にハマったので備忘録として。

lspの導入

lspとは…という説明はいろんなところでなされてるためここでは割愛します。

極ありふれた表現で簡単に表現すれば補完できるすごいやつです。凄いやつは使いたくなりますよね、vimmerならば。

vimrc

ずっと整理したいtomlにできないまま、また一年が経過しそうになってますが、こんな感じです。

  " vim lsp
  call dein#add('prabirshrestha/async.vim')
  call dein#add('prabirshrestha/asyncomplete.vim')
  call dein#add('prabirshrestha/vim-lsp')
  call dein#add('mattn/vim-lsp-settings')
  call dein#add('prabirshrestha/asyncomplete-lsp.vim')
  if executable('solargraph')
      " gem install solargraph
      au User lsp_setup call lsp#register_server({
          \ 'name': 'solargraph',
          \ 'cmd': {server_info->[&shell, &shellcmdflag, 'solargraph stdio']},
          \ 'initialization_options': {"diagnostics": "true"},
          \ 'whitelist': ['ruby'],
          \ })
  endif

公式通りに必要なものをセットで入れてます。

まだ導入段階で解決できてないところ多いんですが、asyncomplete入れてるのに自動補完されないんですよね…それはまた今度調査します。

Rubyではlsp用のgem solargraphを使用するのでとりあえずローカルにぶち込みます。

$ gem install solargraph

とりあえず準備OK。

適当にRailsプロジェクトのファイルを開く

app/controllers/users_controller.rbを開いたとしましょう。

Please do :LspInstallServer to enable Language Server ~~~と出てくるので:LspInstallServerでlspの設定。対象のgem等がインストールされていくはずです。

が、安定のnokogiriさんに阻まれました。

/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10/libtool: File name too long
Makefile:1015: recipe for target 'install-libLTLIBRARIES' failed
make[3]: *** [install-libLTLIBRARIES] Error 126
make[3]: ディレクトリ '/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10' から出ます
Makefile:1792: recipe for target 'install-am' failed
make[2]: *** [install-am] Error 2
make[2]: ディレクトリ '/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10' から出ます
Makefile:1479: recipe for target 'install-recursive' failed
make[1]: *** [install-recursive] Error 1
make[1]: ディレクトリ '/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10' から出ます
Makefile:1786: recipe for target 'install' failed
make: *** [install] Error 2
========================================================================
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/home/motty/.asdf/installs/ruby/2.6.3/bin/$(RUBY_BASE_NAME)
        --help
        --clean
        --use-system-libraries
        --enable-static
        --disable-static
        --with-zlib-dir
        --without-zlib-dir
        --with-zlib-include
        --without-zlib-include=${zlib-dir}/include
        --with-zlib-lib
        --without-zlib-lib=${zlib-dir}/lib
        --enable-cross-build
        --disable-cross-build
/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:402:in `block in execute': Failed to complete install task (RuntimeError)
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:373:in `chdir'
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:373:in `execute'
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:120:in `install'
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:155:in `cook'
        from extconf.rb:365:in `block (2 levels) in process_recipe'
        from extconf.rb:257:in `block in chdir_for_build'
        from extconf.rb:256:in `chdir'
        from extconf.rb:256:in `chdir_for_build'
        from extconf.rb:364:in `block in process_recipe'
        from extconf.rb:262:in `tap'
        from extconf.rb:262:in `process_recipe'
        from extconf.rb:557:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/extensions/x86_64-linux/2.6.0/nokogiri-1.10.10/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10 for inspection.
Results logged to /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/extensions/x86_64-linux/2.6.0/nokogiri-1.10.10/gem_make.out

An error occurred while installing nokogiri (1.10.10), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.10.10' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  solargraph was resolved to 0.40.0, which depends on
    reverse_markdown was resolved to 2.0.0, which depends on
      nokogiri

親の顔ほどみたエラー。つらい。

動いてるスクリプトに設定を追加

自分が使っているパッケージマネージャーはdein.vimです。

dein配下にあるsolargraphのスクリプトを確認してみます。パスは$HOME/.cache/dein/.cache/.vimrc/.dein/installer/install-solargraph.shでした(人によって違うと思うのでファイル名で検索するのもありかも)

#!/usr/bin/env bash

set -e

git clone --depth=1 https://github.com/castwide/solargraph .
bundle install --without development --path vendor/bundle

cat <<EOF >solargraph
#!/usr/bin/env bash

DIR=\$(cd \$(dirname \$0); pwd)
BUNDLE_GEMFILE=\$DIR/Gemfile bundle exec ruby \$DIR/bin/solargraph \$*
EOF

chmod +x solargraph

とりあえず、よく解決する設定をこのファイルにぶち込みます。

#!/usr/bin/env bash

set -e

git clone --depth=1 https://github.com/castwide/solargraph .
bundle config build.nokogiri --use-system-libraries # これ
bundle install --without development --path vendor/bundle

cat <<EOF >solargraph
#!/usr/bin/env bash

DIR=\$(cd \$(dirname \$0); pwd)
BUNDLE_GEMFILE=\$DIR/Gemfile bundle exec ruby \$DIR/bin/solargraph \$*
EOF

chmod +x solargraph

gem追加

もう一点。エラーメッセージにあった、mini_portile関連でエラーになってるっぽかったのでローカルに追加します。

$ gem install mini_portile

とりあえずこれで設定はおk。

LspInstallServer再実行

はい、うまくいったー。

調べても全く出てこなかったので、自力で頑張ってみました。

vim-lspでgem関連エラーが出る場合は実行スクリプト内でgemの操作をやってみるといいかもしれませんね。

それでは、おつでした。

【Ruby on Rails】rails consoleでActionDispatch::Http::Uploadedfileを作成・保存する

どうもてぃ。

久しぶりのRailsで少々ハマったのでメモをば。

やりたいこと

ローカルのファイルを読み込んで、carrierwaveに割り当てているカラムに保存したい。

ただそれだけ。

Let's go

まずはファイルの読み込み。

今回はtmp/uploads/配下にファイルを作っているものとします。

path = Dir.glob(Rails.root.join('tmp', 'uploads', 'test.pdf'))

filename = File.basename(path)
tempfile = File.open(path)

とりあえずこれで準備はおk

ActionDispatch::Http::Uploadedfileで読み込む

上記を使って読み込みます。

uploaded_file = ActionDispatch::Http::Uploadedfile.new(
  filename: filename,
  type: 'application/pdf',
  tempfile: tempfile
)

User.first.update(file: uploaded_file)

UserモデルにUserFileUploaderをマウントしたfileカラムがあるものとして保存してます。

class User < ApplicationRecord
・
・
・
  # ↓こういうやつ
  mount_uploaders :file, UserFileUploader 
・
・
・
end

終わり

ファイルタイプによってtypeをimage/jpegとかに変えれば画像もちゃんと保存できます。

定期的にRailsに触っておかないと忘れちゃいますね。

【Golang】sql-migrate upがCannot parse dateと出てうまくいかないとき

f:id:rdwbocungelt5:20200720165613p:plain

どうもてぃ。

今日もGolangやっていきます。

マイグレーションを実行してみた

% docker-compose exec golang sql-migrate up -config=config/dbconfig.yml
Migration failed: Cannot parse dates.

Make sure that the parseTime option is supplied to your database connection.
Check https://github.com/go-sql-driver/mysql#parsetime for more info.

上記のようにエラーになってしまいます。

sql-migrate newはうまくいってますが、upがうまくいかない。コード上でparseTimeとかつかっているところなんてない。

ただ、エラーメッセージを見てみると、

Make sure that the parseTime option is supplied to your database connection.

これですよ。

parseTimeオプションを追加しろと。

github.com

parseTimeはbool型のようなので、dbconfig.ymlの接続設定にparseTime=trueを追加しました。

development:
  dialect: mysql
  dir: pkg/db/migrations
  datasource: root:password@tcp(db:3306)/database_name?parseTime=true

これでマイグレーションが通るようになりましたとさ。

【Rails】enumからi18nを適応したhashを取得したいとき

どうもてぃです。

enumについてあんまり理解してなかったのでメモとして残します。

gemのenum_helpを入れている状態です。

環境

% lsb_release -a
No LSB modules are available.
Distributor ID: LinuxMint
Description:    Linux Mint 19.3 Tricia
Release:    19.3
Codename:   tricia

TL; DR

User model

class User < ApplicationRecord
  enum role: { admin: 0, manage: 1, guest: 2 }


・
・
・
end

locales/js.yml

ja:
  enums:
    user:
      role:
        admin: 管理者
        manage: マネージャー
        guest: 一般
・
・
・

コンソール

pry(main)> User.roles
=> {"admin" => 0, "manage" => 1, "guest" => 2}

pry(main)> User.roles_i18n
=> {"admin" => "管理者", "manage" => "マネージャー", "guest" => "一般"}

終わり

Userのインスタンスから取得することもできますが、今回はインスタンスを生成せずにenumを使いたかったので、i18nを試してみたらいけました。

User.roles_i18n.invertとすればselect_boxとかに使えそうですね。