GrafanaでZabbix/CloudWatchのメトリクス監視を一元化する
Grafanaかっこいいですよね。いつまでも見ていられそうです。
今回は統合監視ツールZabbixとAWSのCloudWatchメトリクス群を Grafanaで一元的に可視化して見れるようにしてみます。
今回の背景
CloudWatchやEC2のメトリクスを見るのに、 AWSにコンソールで入っていちいち確認するの面倒じゃないですか。 加えてサービスごとにAWSアカウントが分かれているとなると更に不便じゃないですか。
・よりリアルタイムなデータを見たいものはZabbixのメトリクスを使用したい
・ELBにアタッチされてるホストの数も見たい
・オートスケーリングどんな感じか見たい
・インスタンス毎のメトリクスも見たい
・ついでにサービス全体でどれくらいの負荷がかかってるかも見たい
・なんなら複数のAWSのアカウントを跨いで見れると尚良い
・・・ということで全部grafanaに突っ込みました。
構成
今回のメインはzabbix-server、Grafana及びCloudWatchあたりになります。
構成はこんな感じです。
Grafanaは標準でCloudWatchをサポートしていて、 Zabbixもプラグインを入れることでデータソースとして使用することが可能です。
ちなみにGrafanaで標準サポートされているデータソースがこちら
・CloudWatch
・Elasticsearch
・Graphite
・InfluxDB
・OpenTSDB
・Prometheus
Zabbixも標準でサポートしてくれると嬉しいです。
grafanaをインストールする
インストールはOSはUbuntuベースで話を進めていきます。
Ubuntu以外に関してのGrafanaのインストールは、詳しくはこちらをご覧ください。
$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_4.1.1-1484211277_amd64.deb $ sudo dpkg -i grafana_4.1.1-1484211277_amd64.deb $ sudo apt-get install grafana
grafanaにZabbixのプラグインをインストール
$ sudo grafana-cli plugins install alexanderzobnin-zabbix-app
GitHub - alexanderzobnin/grafana-zabbix: Zabbix plugin for Grafana dashboard
grafanaを起動
$ sudo service grafana-server start
Grafana自体にHTTPサーバーの機能も内臓されているので、これでGrafanaが立ち上がります。 デフォルトでは3000番ポートを使用するので、適宜リバースプロキシでnginxを前にかませるといいかと思います。そのままでも問題なく使えます。
では次にZabbixのデータを取り込んでいこうと思います。
Zabbix側でgrafana用のユーザーを作成
Zabbix側の手順としては
・grafana用のユーザーを作成する。
・grafana用ユーザーにREAD権限を付与。
といった流れになります。
ちなみにZabbix側でgrafanaユーザーに適切なパーミッションを与えていなかった結果、grafanaからAPI叩いてもデータが取れずに2時間ばかり無駄にしたのは私です。 パーミッションを与えてください。
Zabbixのパーミッションなどは本家にドキュメントがあります。
grafanaでZabbixデータソースの設定
左上のロゴから、[Data Sources] → [Add data source]と辿っていきます。
設定はこんな感じです。
Zabbixには標準でAPIが用意されているので
http://エンドポイント/zabbix/api_jsonrpc.php
をURLのところに設定してあげます。
Zabbix API Detailsには先ほどZabbix側で作成したgrafana用ユーザーのUsernameとPasswordを設定してください。
今回は便宜上、Zabbix Serverが入っているEC2インスタンスにGrafanaも入れているのでVPCやSGなどは特に気にせず、GrafanaをプロキシとしてlocalhostでZabbixのエンドポイントを叩いています。
Zabbix用のダッシュボードを作成
ダッシュボードの作り方などはServerworksさんのこちらのブログが詳しいです。
個人的な要件:EC2のメトリクス表示をオートスケーリングに対応させたい
Grafanaでダッシュボード作ったのはいいものの、 オートスケーリングでインスタンスが増減するたびにグラフの設定し直すのとかめちゃめちゃ面倒ですよね。
そもそもオートスケーリングしなくてもインスタンス多いとグラフ作るのが面倒。
でも1つのパネルで全インスタンスのCPU利用率とか表示させたい。
解決策:正規表現でフィルタリングができる。
文字が黄色くなっている箇所ですが、Host名でフィルタをかけて、ホスト名がマッチするサーバー群のメトリクスを一発で表示することができます。
上の設定だけでこんなグラフがすぐに出来上がります。
これだけでもパネル設定がかなりラクになりました。
そのほかの色々なグラフなどの作り方はgrafana-zabbix.orgが出しているデモの設定が参考になります。
http://play.grafana-zabbix.org/dashboard/db/grafana-zabbix-demo
GrafanaでCloudWatchをデータソースに設定する
続いてGrafanaにCloudWatchのデータを取り込んで、グラフを表示させていきます。
AWS IAMでgrafana用のユーザーを作成
CloudWarchReadOnlyAccess
ポリシーをアタッチしたユーザーをIAMで作成します。
Grafanaの方で使用する認証情報はアクセスキー及びシークレットキーになります。
GrafanaでCloudWatchデータソースの設定
本家Grafanaのドキュメントではaws-cliのクレデンシャルファイルを使用した設定方法となっていますが、 設定画面から直接IAMユーザーのアクセスキーとシークレットキーを入れることも可能です。
個人的にはサーバーの中に credential
を置く必要ないので、GUIで設定しちゃうとがラクかなと思います。
GUIで設定しても、再度設定を開くとアクセスキーなどは見れないようになっています。
これでCloudWatchの方からもメトリクスを表示が可能となりました。
複数のAWSアカウントを設定する際も同じ要領でIAMユーザーを作成し、データソースを追加していくことでGrafanaからデータを取り出せます。
ELBのHealthyHostCountをパネルに表示する
試しにCloudWatchからのメトリクスとしてELBにアタッチされているHealthyHostCountのメトリクスを表示させてみます。
設定としてはこんな感じです。
これでZabbix及びCloudWatchからデータが取れるようになったので、あとはパネルを一通り作れば、完成です!
【番外編】 AWSの請求情報をgrafanaで確認する
AWSの請求情報、ついでにGrafanaで見たくないですか? 私は見たいです。
例えばこんな感じ。
Grafanaの公式サイトにあるテンプレートを使えばすぐに表示させることができます。
上記のものだとインポートした後にカスタマイズができないので、 インポートした後にカスタマイズしたいという方には、カスタマイズできるやつ置いておきます。
よかったら使ってください。
GitHub - yoshi42662/Grafana-AWS-Billing-Dashboard
We’re hiring!!
Cluexではビジネスサイド、エンジニアサイド共にメンバーを募集しています! お気軽にご連絡下さいませ! エンジニアの方、ぜひ情報交換しましょう!
男もすなるsshといふものを、我もしてみむとて解説するなり
こんにちは。エンジニアでインターンをしている村田です。 最近寒くてベッドから起き上がるのがつらいです。
最近デスクトップ環境をxubuntuにしたのですが使いやすくて感動してます。 軽くて、Ubuntuらしい便利な機能も多くありますので他の方にもぜひおすすめです!
話は変わりますが、コンピュータの用語で新しく知ったものを調べると なんでこんなにわかりづらい説明しかないんだ!! と思ったことってありませんか?
自分は結構多いです、この現象(笑)。 学習していくとそれが当たり前になってしまうので「このサイトにわかりやすく書いてあるじゃん」と思うのですが、最初は難しく感じてしまうものなんですよね。
今回は以前自分が概念を理解するまでに苦労してしまった「sshのしくみ」についてまとめていこうと思います。 (「わかりやすい」というのは個人的な感想です。)
「ssh」略さずに言うと?
「ssh」はsecure shellの略です。 日本語にすると安全なシェルということです。
「ssh」っていつ使うの?
「sshとは安全なシェルのことです!」と言われてもそれではなんのことかわからないと思いますので、もう少しかみ砕いて説明していきます。 このページをご覧になっている方は、例えば「サーバーにアクセスしようとしたけどsshってどういうことなんだ?」とか「GitHubを使ってみたいけどなんか登録してsshを使わなくちゃいけないらしい」といった方が多いかと思います。
それではsshとはどういう場面で必要なのでしょうか?
簡単な言葉で説明すると「他のコンピュータに対してアクセスして、何かしらの操作を加えたいとき」にsshを使います。 例えば「サーバーに対してコマンドを実行して環境を作りたい」とか「GitHubなどのリモートリポジトリに対してブランチをマージさせたい」といったところで、sshというコマンドを使用したいわけです。
基本的にはssh user@host_name
で使います。
これは色々なところで書いてあるのでわかりやすいと思います。
そもそも、「安全なシェル」の「シェル」とは人間とコンピュータが気軽におしゃべりするための言語です。 ディレクトリを変えたり、 ファイルを削除したい!というときの「cd」とか「rm」はそれに当たりますよね。
遠くのコンピュータに命令したいときも当然同じようにおしゃべりできたら便利なわけですから、シェルを使いたいですよね。 ただし、暗号化なしで通信するとほかの人に見られる危険などがあるため安全なシェルすなわちsshを使いたいということなのです。 (実は以前は暗号化されていないtelnetというものを使っていました。基本的な機能しかないことを利用して、現在もサーバーを作る際にときどき用いることがあります。)
暗号化の仕組み
sshで公開鍵暗号方式を使用しています。(実は違うやり方でパスワード認証方式というのもありますが、あまり使われないように思われます。) 公開鍵暗号方式の通信とはサーバーに公開鍵を持たせて文書等を暗号化させて、受信する際には自分の持っている秘密鍵を使用して複合する通信のことです。
これを例えるとすると、 公開鍵を錠(lock)、秘密鍵はその錠の鍵(key)だと考えてください。
南京錠などを想像すればわかるように、lockのやり方がわかっても、keyが用意できなければ実際に中身にたどり着くことはできません。 リアルの世界とは違って暗号化の世界では錠の鍵穴を見て鍵を作り出すことができない(らしい)ので、自分の秘密鍵をばらさなければこれで安全に通信することが可能なわけです。
また、sshではより安全性を高めるために秘密鍵に対して鍵をかけるのが一般的です。 鍵に鍵をかけるというのは面白いですよね。
この鍵は暗号化も複合化も同じ共通鍵暗号方式を使用しています。
実際に使用していくコマンド
ここでは実践で使っていくコマンドを簡単に紹介していきます。 紹介できなかったオプションやコマンドがたくさんあると思うので、不足している部分に関しては最後の参照URL等をご覧ください。
また事前知識としてsshに関するファイルは~/.ssh
というディレクトリに入るのですが、そこのファイルの役割を紹介しておきます。
authorized_keys 公開鍵を登録しておくファイル。 config SSH接続に関する設定を書いておくファイル。 known_hosts 過去に接続したことがあるサーバーを書いておくファイル。
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
これはgithubで推奨されている鍵の作り方です。
-t rsa
の部分はRSAという暗号化方式を使って作成するという意味です。
他にもDSAやECDSAといった種類がありますが一般的にはRSAを用いるのではないかと思います。
また-b 4096
では鍵のビット数をしてしています。デフォルトでは2048になのでより強固に作成していると言えますね。
-C "your_email@example.com"
の部分はコメントなので必要なければ省いて構いません。
途中でパスフレーズを聞かれると思いますが、これが先ほど書いたとおり秘密鍵に対するパスワードになっているので忘れないものを使用してください。
このコマンドを実行するとid_rsa
とid_rsa.pub
が作成されます。もちろん前者が秘密鍵、後者が公開鍵です。
余談ですが、GitHubユーザーのSSH鍵6万個を調べてみたでGitHubのssh鍵に関して面白い考察がありました。
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host_name
これはsshの公開鍵を登録したいサーバーに送るコマンドです。
i
オプションで任意のファイルを指定して送ることができます。ここでは先程作成した~/.ssh/id_rsa.pub
を指定しています。
ssh-agentとssh-add ~/.ssh/id_rsa
ssh-agent
は認証エージェントとよばれるもので、sshをするときに必要なパスワードの入力をショートカットできるようにするコマンドです。
(ubuntuやMacの人は自動的に起動しているのでこのコマンドは忘れてしまっても問題ありません。ただ、他のOSではssh-agent bash
などを打たないといけないかもしれません。)
ssh-add
はssh-agent
に秘密鍵を追加するメソッドです。
引数にとった秘密鍵を追加します。
参照URL
http://qiita.com/tag1216/items/5d06bad7468f731f590e http://qiita.com/suthio/items/2760e4cff0e185fe2db9 http://webos-goodies.jp/archives/50672669.html
またこちらは書籍ですが、私がsshの仕組みを少し理解できるようになったきっかけになった本です。 はじめてUNIXで仕事をする人が読む本
HTMLテンプレートエンジン「slim」の解析ツールslim-lintを導入してみた!
こんにちは、エンジニアの井戸田です。
弊社ではmamanokoという子育てをするママのためのメディアをRuby on Railsで運営しており、viewではHTMLテンプレートエンジンであるslimを使用しています。今までrubyの解析ツール rubocop
や、scssの解析ツール scss-lint
は導入しましたが、slimの解析ツールを導入していなかったということで、今回導入してみました。
インストール
$ gem install slim_lint
又は Gemfile
に下記を記入して bundle install
をすることでインストールが可能です。
gem 'slim_lint', require: false
require: false
を指定することで、 autorequire
をしないようにしています。
実行方法
スキャンするディレクトリ、又は複数のディレクトリを指定することによって、コマンドラインから slim-lint
を実行することが可能です。
$ slim-lint app/views $ slim-lint app/**/*.slim
又 slim-lint -v/--version
を指定するとバージョンを確認ができます。他にもいろいろなオプションがあるので、下記のURLから御覧ください。
ref) https://github.com/sds/slim-lint#usage
実装
slim-lintはデフォルトで下記のような設定になっています。
ref) https://github.com/sds/slim-lint/blob/master/config/default.yml
# Default application configuration that all configurations inherit from. # # This is an opinionated list of which hooks are valuable to run and what their # out of the box settings should be. # Whether to ignore frontmatter at the beginning of Slim documents for # frameworks such as Jekyll/Middleman skip_frontmatter: false linters: CommentControlStatement: enabled: true ConsecutiveControlStatements: enabled: true max_consecutive: 2 EmptyControlStatement: enabled: true RedundantDiv: enabled: true LineLength: enabled: true max: 80 RuboCop: enabled: true # These cops are incredibly noisy since the Ruby we extract from Slim # templates isn't well-formatted, so we ignore them. # WARNING: If you define this list in your own .slim-lint.yml file, you'll # be overriding the list defined here. ignored_cops: - Lint/BlockAlignment - Lint/EndAlignment - Lint/Void - Metrics/LineLength - Style/AlignHash - Style/AlignParameters - Style/BlockNesting - Style/FileName - Style/FirstParameterIndentation - Style/FrozenStringLiteralComment - Style/IfUnlessModifier - Style/IndentationConsistency - Style/IndentationWidth - Style/MultilineArrayBraceLayout - Style/MultilineAssignmentLayout - Style/MultilineHashBraceLayout - Style/MultilineMethodCallBraceLayout - Style/MultilineMethodDefinitionBraceLayout - Style/MultilineMethodCallIndentation - Style/MultilineOperationIndentation - Style/Next - Style/TrailingBlankLines - Style/TrailingWhitespace - Style/WhileUntilModifier TagCase: enabled: true TrailingWhitespace: enabled: true
この設定の中で、不要・変更したい設定に対して、ホームディレクトリに .slim-lint.yml
というファイルを作成し、記述することで無効化・変更します。
.slim-lint.yml
の記述例
exclude: - 'repository_name/app/views/**/*.slim' linters: CommentControlStatement: enabled: false LineLength: include: 'repository_name/app/views/**/*.slim' max: 80 EmptyControlStatement: exclude: 'repository_name/app/views/**/*.slim'
オプション | 説明 |
---|---|
exclude | slim-lintや各linterから除外したいファイルがある時に使用します。 |
include | 指定したファイルで絞り込みを行います。 |
enable | false とした時には、そのlinterが走ることはありません。そのlinterが不要な時に使用します。 |
linterの説明
CommentControlStatement
コメントの書き方についての制御するlinterです。
- Bad
# commentout
- Good
/ commentout
ConsecutiveControlStatements
連続の制御文に対して制御するlinterです。
ConsecutiveControlStatements
には下記ようなオプションがあります。
制御構文が同じインデントで2行以上続くのでしたら、見やすさからviewに書かずに helper
にその制御を移動させた方がいいと思います。
オプション | 説明 |
---|---|
max_consecutive | 行に指定できる制御文の最大数 |
- Bad
- code1 - code2 - code3
- Better
ruby: code1 code2 code3
- Good
- helper_method_name
EmptyControlStatement
空行に対して制御するlinterです。
こちらのlinterを true
にすると空行がなくなり、場合によっては見づらくなる可能性があるので、注意する必要がありそうですね。
- Bad
p pタグ - p pタグ
- Good
p pタグ p pタグ
RedundantDiv
div
タグに対して制御するlinterです。
slimでは div.class_name
と書かずに .class_name
と記述するだけで divタグ
になります。不要な場合に div
と記述しないというのが、このlinterの役割です。
- Bad
div.class_name
- Good
class・idを指定せず、ただの改行などの場合に使用する場合にはdiv
と記述する必要があります。
div
- Good
.class_name
RuboCop
このlinterはテンプレート内に存在する Ruby
コードをチェックする為のものです。
ホームディレクトリに作成された .rubocop.yml
の内容が反映されるようです。
ref) https://github.com/bbatsov/rubocop
オプション | 説明 |
---|---|
ignored_cops | 無視したいRubocopの設定を記述 |
TagCase
大文字のタグ名を報告するlinterです。
HTMLの標準では、小文字のタグ名を限定するということはなく、大文字でも対応できるのですが、XHTMLでは小文字の記述が必須なので、一貫性としてこのlinterが作られたようです。
個人的に大文字・小文字が混ざっているいると見づらい点や、小文字にすることで大文字より見やすくなる点があるので、小文字で揃えた方がいいと思います。
- Bad
BODY p pタグ
- Good
body p pタグ
いかがでしたでしょうか?
slim-lint
を導入することで、気をつけて同じフォーマットにしようとしていても、どうしても見逃してしまう部分や、行数を制限することで、1つのファイルだけで処理するのではなく、partial化させることにより見やすくなると思います。
最後まで読んでいただきありがとうございます。
We’re hiring!
フロントエンジニアの方で、サーバーサイドを触ってみたい方、ぜひ一度Cluexに遊びに来てください!!
AWSのCloudFrontからコンテンツをHTTP2 & gzipで高速に配信する
こんにちは、高橋です。
みなさん快適で楽しいAWSライフを送れていますか?
実は2ヶ月ほど前、AWSからCloudFrontでHTTP2によるコンテンツの配信ができるようになったので早速導入して見ました。
Amazon CloudFront now supports HTTP/2
S3のバケットにあるCSSやJS、画像などのアセットをCloudFrontから配信するというパターンは AWSでインフラを構築するサービスではよくあると思います。
今回はこういったS3上にあるアセットをHTTP2とgzipを使用してCloudFrontから配信するための設定方法などを見ていきたいと思います。
設定そのものは3分くらいで終わります。
CloudFrontにHTTP2を適用する
先ずはAWSのコンソールを開き、CloudFrontを選択します。
リンクまたはチェックボックスを押して「Distribution Settings」からディストリビューションの設定画面に飛びます。
「General」タブの「Edit」ボタンから基本設定の変更ページへ飛びます。
「Supported HTTP Versions」をHTTP2が含まれているものを選択して、右下の「Yes, Edit」ボタンを押します。
ちなみに「Supported HTTP Versions」の右にある黒いボタンを押すと、下記のような説明が出てきます。
For viewer requests, choose the versions of the HTTP protocol that you want CloudFront to accept. In general, HTTP/2 is faster. CloudFront always forwards requests to the origin using HTTP/1.1.
日本語にすると
ユーザーからCloudFrontへのリクエストの際に使用するHTTPプロトコルを選択してください。一般的にHTTP2は速いっすよ。CloudFrontからオリジンへのリクエストはHTTP 1.1だけ使うでー。
といった感じでしょうか。
ユーザーからのリクエストはHTTP2を使用できますが、CloudFront内部でのリクエストではHTTP2はまだ未対応のようです。
とはいえ、ひとまずこれで設定完了です!楽勝ですね!
あとは設定が完了するまで時間を潰して、 設定が完了したらブラウザから確認できればOK!
Chromeなどのブラウザのデベロッパーツールから見てみると.....
レスポンスは304になっていますが、「Protocol」のところが「h2」になっていれば設定完了です!
CloudFrontでgzip圧縮による配信をする
では次にファイルをgzip圧縮して配信する設定を見ていきましょう。
先ほどのディストリビューションの設定画面に飛びます。
今回は「Behaviors」タブを選択して、gzip配信にしたいものにチェックボックスを入れて「Edit」を押します。
下にスクロールしていくと、一番下に「Compress Objects Automatically」という設定項目があるので、「Yes」を選択してから右下の「Yes, Edit」を押して設定完了!
ちなみに「Compress Objects Automatically」の右にある黒いボタンを押すと、下記のような説明が出てきます。
Select whether you want CloudFront to automatically compress content for web requests that include Accept-Encoding: gzip in the request header. CloudFront compresses files of certain types for both Amazon S3 and custom origins.
日本語にすると
わいに頼んでくれたらリクエストヘッダにAccept-Encoding: gzipがあった時はCloudFrontの方でコンテンツの圧縮しとくで。S3とか別のオリジンのファイルでも圧縮できそうなら、わいが勝手にしとくやでー。
といった感じでしょうか。
圧縮倍率はCloudFrontの方でよしなに決めてくれるようです。
ということで設定が終わったのでブラウザから確認して見ましょう!
先ほどと同様にChromeなどでデベロッパーツールを開き、CloudFrontから配信されているファイルのレスポンスヘッダを確認します。
「content-encoding: gzip」となっていますね!
これでCloudFrontにHTTP2とgzip配信の設定が完了しました!
手軽にできてすぐに効果が期待できるので、気になった方は試して見てください!
We're hiring!
Cluexではビジネスサイド、エンジニアサイド共にメンバーを募集しています! お気軽にご連絡下さい!
Mockを使って、Facebookログイン部分のRSpecを書いてみた!!
こんにちは、エンジニアの神山です。 最近、テストカバレッジを上げるためRSpecを書きまくっています。ちなみに最初は90%でしたが、苦闘の末95%まで上がりました。結構骨が折れましたね。
その中でも大変だったのがFacebookログイン部分のテストです。外部APIを使っており、そこの部分のテストの書き方が分からなくて悩んでいました。 色々と調べてみるとモックを使うとうまいことテスト出来るよという文献を見つけました。
ということで今回は、外部API部分のテストの問題点、モックとは何か、またそれをどのようにテストに使うのかにフォーカスして記事を書きました。
外部API部分のテストの問題点
今回悩んだのは外部APIを使用している部分のテストをどのように書くかということです。
例えば、「ログインしようとしているユーザーのFacebookのアカウント情報を取得し、すでにDBに登録されていればログインさせる」ということです。 しかしこのテストを行うには、実際にFacebookAPIよりアカウント情報を取得しなくてはいけません。
しかしテストで外部APIを利用することには、幾つかのデメリットがあります。
- 外部APIやその周辺で、予測や対応ができないエラーが起きることがある
- 外部APIの使用に制限があったり、金銭などが発生する場合がある
- 外部APIに紐付いているプロダクトにリアルに影響が起こる(Facebookの場合、実際に投稿がされてしまうなど)
では、どうすれば外部APIを利用せずに、外部API部分を使用している部分のテストを出来るのでしょうか。 そのようなときに使うのが、「モック」です。
モックとは何か。
モックを直感的に説明すると、「本物のふりをするニセモノのプログラム」です。下記の記事の言葉を使わせて頂きました。
例えばユーザーのFacebook情報を取得するとき、FacebookAPIにリクエストが発生したら予め用意したニセモノのプログラムを呼ぶようにすることが出来ます。 また「aが呼ばれたときに本当はbを返すのだけど、ここのテストだけはcを返したい」というときに使用したりもします。
つまりモックとは、外部APIなどテストを行うために必要だけれど使用できない、再現することが難しい場合に、その役割を担ってくれるものです。
ちなみにモックとスタブの違いは?
モックと似た言葉にスタブというものがあります。気になって調べてみたのですが、両者の違いは使用目的だそうです。基本的にどちらもニセモノを作り出すことには変わらないようです。
ただその違いを明確に理解するのはなかなか難しく、またあまり意識する必要もないという意見もあったので、今回は保留にしました。時間があるときに色々と調べてみようと思います。
ちなみに、分かりやすく書いてある記事があったので、載せておきます。
モックの準備
Omniauth
部分のテストに関しては以下に従っております。
まずモックにすべきところを整理しましょう。 今回はユーザーのFacebook情報を取得する際にFacebookAPIを用います。そしてFacebookに登録されている名前やEmailを取得します。 そのため、今回モックにするところはFacebookAPIにリクエストがあったときに返す部分です。 以下をHelperに記します。
def facebook_mock(name, email) OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new( provider: 'facebook', uid: 1234567890, info: { name: name, email: email }, credentials: { token: 'hogepiyo1234' } ) end OmniAuth.config.test_mode = true
たとえば、facebook_mock('foo', 'bar')
とすれば、以下の値が得られます。
{ provider: 'facebook', uid: 1234567890, info: { name: 'foo', email: 'bar' } , credentials: { token: 'hogepiyo1234' } }
またOmniAuth.config.test_mode = true
はOmniauthを用いたテストの際に必要になるので、一緒に記述しておいてください。これを記述すると、FacebookAPIにリクエストが送られそうになると、それを中止してすぐにコールバックしてくれます。
RSpec
では、Facebookログイン部分の一連のテストを書いていきます。
まず、ユーザーを作成します。
let(:user) { User.create(name: 'hoge', email: 'hoge@hoge.com') }
テストの前にOmniAuth.config.mock_auth[:facebook]
を初期化し、facebook_mock
をセットします。
OmniAuth.config.mock_auth[:facebook] = nil Rails.application.env_config['omniauth.auth'] = facebook_mock( name: user.name, email: user.email )
準備はこれだけです。では実際にFacebookログインをしてみます。今回は分かり易くボタンを押してFacebookログインをする形式にしてみました。
click_link 'Facebookを利用してログインする'
さて、ボタンが押されると通常はFacebookAPIにリクエストが走りますが、テストではすぐにコールバックされます。
ただモックのおかげで、request.env['omniauth.auth']
には下記の値が入っております。
{ provider: 'facebook', uid: 1234567890, info: { name: 'hoge', email: 'hoge@hoge.com' } , credentials: { token: 'hogepiyo1234' } }
そのため、request.env['omniauth.auth']['info']
でname: 'hoge', email: 'hoge@hoge.com'
の組み合わせを取得できるようになります。あとはこれをDBと照合して、有効であるかどうかを確かめればテスト終了です。
テスト全体は以下のようになります。
discribe 'login via Facebook' do let(:user) { User.create(name: 'hoge', email: 'hoge@hoge.com') } before do OmniAuth.config.mock_auth[:facebook] = nil Rails.application.env_config['omniauth.auth'] = facebook_mock( email: user.email, name: user.name ) click_link 'Facebookを利用してログインする' end it 'should succeed' do expect(page.status_code).to eq 200 end end
ちなみに検証部分がステータスコードの判別しかないですが、ログインされているかどうかを簡単に確認できる指標が欲しいですね。
例えば、expect(current_user).to eq user
のようなものがあれば。。
以上、Mockを使ったRspecの書き方でした。読んで頂きありがとうこざいました。 アドバイスなどありましたら是非お願いします!
We're hiring!
Cluexではビジネスサイド、エンジニアサイド共にメンバーを募集しています! お気軽にご連絡下さい!
参考文献
Docker for Macが遅い問題をdocker-syncで解決する
こんにちは。エンジニアの志村です。 Docker for Mac便利ですね!
日本語でも様々な記事が出てきています。
私もVagrant + Dockerをメインに使用しておりましたが、ついにDocker for Macに乗り換えました。
弊社では、dev環境をDockerにしているのですが、Vagrant + Dockerの時は快適に開発が出来ました。
ただ、VMを使わなくなった途端にめちゃくちゃ動作が重くなりました。
docker-compose --service-port ●●
という感じで、rails serverとwebpack-dev-serverを立ち上げるのですが、ブラウザからの読込が劇的に遅い…。seedデータ突っ込むのもめちゃくちゃ遅い…
フォーラムでも話題になっていますね。
私の環境でいうと、Vagrant + Dockerの時よりも、体感10倍近く速度が落ちました…。
なぜ遅いのか
このDockerの中の人の回答を見ると、osxfsを用いてファイルシステムイベントを検知・監視していることが主な原因っぽいですね。 勿論、その他環境により差異はありますが、ファイルシステムを監視する方法を替えれば解決できそうです。
docker-sync
ファイル同期で速度早いと良く言われているのがrsyncですね。 docker-dev-osxという選択肢もありますが、これはDocker for Mac未対応… どうしようかなーとフォーラムを眺めているとdocker-syncなるものがありました。 フォーラムの中でも評価が良く、結構な人が使ってそうなのでdocker-syncを使用したいと思います。
docker-syncはRubyベースで書かれています。
docker-syncの使い方
- docker-sync, fswatchをインストールします。
$ gem install docker-sync $ brew install fswatch
ファイルの同期に関してはrsync, unisonが選択出来ます。 rsyncがホスト→ゲストの一方向の通信なのに対し、unisonはNFSのように双方向の通信が可能なようです。 今回はrsyncを使用します。 unisonに関してはまた記事を書ければと思います。
$ brew tap homebrew/dupes $ brew install rsync
※ schema.rb, Gemfile.lock等、ゲスト(Docker)側で生成されるファイルに関してはdocker cp
コマンドを使用するとホスト側に持ってくることが出来ます。
# Docker内のschema.rbをPC側に持ってくる
$ docker cp コンテナ:/var/www/db/schema.rb ./db/schema.rb
- docker-syncの設定 docker-syncはymlファイルに設定を記述します。 Railsを触っている身としては普段から使用しているのでありがたいです。
docker-syncはDocker Composeを使用します。 production環境やstaging環境でもDockerを使用している方は、docker-compose.ymlの他に、開発環境用のymlファイルを用意する必要があります。 私は開発環境のみなので、docker-compose.ymlを直接編集してしまいます。
公式のwikiに載っているので参考下さい。
docker-sync.yml
syncs: # docker-syncで使用するvolume名を記載 web-sync: notify_terminal: true # ホスト側(PC)のパスを記載 今回はRailsのルートディレクトリを指定 src: './' # ゲスト側(Docker)にマウントするパスを記載 Docker内の/var/wwwにマウントされる dest: '/var/www' # IPの設定 sync_host_ip: '127.0.0.1' # rsyncのポート設定 sync_host_port: 10871 # rsyncさせないファイル類を記載 sync_excludes: ['Gemfile.lock', 'Gemfile', 'config.rb', '.sass-cache/', 'sass/', 'sass-cache/', 'composer.json' , 'bower.json', 'package.json', 'Gruntfile*', 'bower_components/', 'node_modules/', '.gitignore', '.git/', '*.coffee', '*.scss', '*.sass'] sync_excludes_type: 'Path' sync_args: '-v' # ファイル同期方法の選択 rsync or unison sync_strategy: 'rsync' # ゲスト側でのユーザー名の指定 sync_user: 'test' sync_userid: '5000' # ゲスト側でのgroupの指定 sync_group: 'testgroup' sync_groupid: '6000' # fswatchで変更を検知させないファイルやディレクトリ sync_excludesとかぶせとけばよいかと watch_excludes: ['.*/.git', '.*/node_modules', '.*/bower_components', '.*/sass-cache', '.*/.sass-cache', '.*/.sass-cache', '.coffee', '.scss', '.sass', '.gitignore'] watch_args: '-v' watch_strategy: 'fswatch'
docker-compose.yml
docker-compose.ymlにはversion1, version2と2種類の記述方法があります。 ここではversion2を使用します。
version: '2' services: database: image: postgres:latest volumes_from: - datastore expose: - '5432' elasticsearch: image: elasticsearch:latest volumes_from: - datastore ports: - '9200:9200' redis: image: redis:latest ports: - '6379:6379' volumes_from: - datastore memcached: image: memcached:latest ports: - '11211:11211' volumes_from: - datastore datastore: build: docker/datastore web: build: . command: bash -c 'rm -f tmp/pids/server.pid && bundle exec foreman start && bundle exec sidekiq -C config/sidekiq.yml -L tmp/sidekiq.log -d' volumes: # 下記で宣言したvolume名を指定 - web-sync:/var/www:rw - /var/www/client/node_modules ports: - '3000:3000' - '8080:8080' links: - database - elasticsearch - redis - memcached # docker-syncで使用するvolume ここで宣言した名前がdocker-sync.ymlで使用される volumes: web-sync: external: true
このような感じです。 環境によって差異があると思いますので、適宜調整をお願いします。 一番重要なのは、volumesのsync volumeの設定と、アプリケーション(Rails)側のコンテナでvolumesを指定する部分です。
docker-syncの起動
$ docker-sync start
もしくは
$ docker-sync-stack start
で起動します!
docker-sync-stack start
の場合は、docker-sync start
と同時にdocker-compose up
も行われます。
私はpry-byebugを使用したいので、普段docker-compose run --service-port web
で起動しているため、ターミナルを一枚docker-sync startに使用し、さらにdocker-compose run --service-port web
を起動させるようにしています。
ベンチマークはとっていないのですが、Vagrant + DockerをNFSで同期させたのと同じ、もしくはそれ以上に早くなりました! GUIで様々な設定が出来、VMとかも必要ないのでDocker for Macは便利ですね。 是非docker-syncを使って快適な開発環境を構築してみては如何でしょうか?
We’re hiring!
Cluexではビジネスサイド、エンジニアサイド共にメンバーを募集しています! お気軽にご連絡下さいませ!
今年2回目の開発合宿に行って来ました!@土浦・筑波
こんにちは、エンジニアの高橋です。
最近都内は急に肌寒くなってきましたが、みなさんお元気でしょうか?
今回は茨城県の土浦・筑波エリアで開催!
先日、2泊3日で茨城県の土浦・筑波の方に開発合宿に行ってきました!
台風が近づいている中での開催となり、心配な所もありましたが無事に終わったので、 今回はその様子をまとめようと思います。
2月の開発合宿に続いて、今年2回目の開催となります。 Cluexでは合宿を利用して 普段なかなか手のつけられない技術的課題や技術的負債への取り組みや、 理念会議といったメンバー全員でじっくり話し合う場を設けるなど といったことをしています。
ちなみに前回(2016年2月)の日光での合宿の様子はこちら cluex-developers.hateblo.jp
古民家ゲストハウス「jicca」
今回の宿泊先には2泊3日の全日貸切で、筑波山の近くにある 茨城県石岡市のゲストハウス「jicca」さんを使わせてもらいました。
ここのゲストハウスはクラウドファンディングを活用して、 もともと実家の母屋だったものをゲストハウスに改装したそうです。
ここの近辺は豊かな自然が溢れていて、とても落ち着いている長閑な場所で、
jiccaは最近は雑誌やラジオなどで度々話題になっているそうです。
こちらを運営されている比企(ひき)さんという方は、もともと大手企業で活躍された後に 現在はこちらの「jicca」を運営されつつ個人で中小企業診断士として中小企業コンサルをされている方で、とても暖かい方でした。
今回の合宿でのTRY
合宿に参加したのはエンジニア4人・ディレクター3人の合計7名。
合宿中はエンジニア陣は2人で1チーム、ディレクター3人で1チームの全部で3チームに別れて目標を立てました。 合宿の目標はそれぞれのチームであらかじめ決めておき、合宿当日はすぐに作業が開始できる様にしておきました。
ディレクターチーム 売上を上げるためのコンテンツマーケティングの運用方針を決める
今後の事業成長戦略を各々が考えて発表
Web appチーム Rspecのテストカバレッジを95%達成
インフラ&ネイティブアプリチーム CoffeeScriptからES2015(ES6)への完全移行
開発合宿1日目
台風が近づいてる影響で初日は曇り空。
午前9時、都内某所に集まり出発です!
都内から土浦までは高速道路を使用して、車でおよそ1時間半ほどの距離にあります。
新卒3人組
前日も遅くまでオフィスに残っていたみたいで非常に眠そうですね。
土浦までの道中は高速道路も渋滞なく順調に進み、
守谷SAで途中休憩を挟んでほどなくして土浦に到着です。
宿に着く前に、激安ジャングルで物資調達です。
車内では眠そうだった彼も元気になったみたいです。
そして11時過ぎにjiccaへ到着。
到着してからまずは全体で各チームの合宿中の目標を共有し、 終わり次第すぐに各自作業に取り掛かります。
ディレクターチームは主に話し合いが多いので1階にて作業。
エンジニアの方は机と椅子が用意されている2階に上がり作業を開始。
ディレクターチーム
エンジニアチーム
1日目の夜は夕食と温泉を兼ねて、
車で10分ほど移動して「やさと温泉 ゆりの郷」へ行きました。
この近辺は日帰り温泉が500~1000円くらいで点在しているので、 その中から一番近場の場所を選びました。
「jicca」のオーナーの比企さんも一緒に温泉にお供して頂きました。
こちらの常陸牛は柔らかくてとても美味しいお肉でした。
夕食後
本日はアルコールは一切なしで、 夕食を食べた後はすぐ宿に戻って作業再開です。
ディレクターチームは順調に進んでいるようで、午前12時頃には就寝。
エンジニアの方はまだまだ続きます。
午前4時
まだ続きます。
初日が終わり、全員が寝静まったのは午前6時頃。
長い長い1日目が終了です。
開発合宿2日目
台風は進路を変えていなくなってしまい、 晴れ晴れとした天気になりました。
午前9時、起床。
全員で集まり1日のスケジュール確認です。
午前中は引き続き各チームごとで作業。
昼食は手打ち蕎麦が有名とのことで、宿の近くの蕎麦屋さん「かまたや」へ
創業60年以上の老舗蕎麦屋だそうです。
蕎麦はもちろん、天ぷらがめちゃめちゃ美味しいです。
宿に戻り、今回の合宿のもうひとつの一大イベントに入ります。
Cluex理念会議
2日目は昼食後から6時間ほどに渡り、
ディレクター・エンジニア含めて全員で「理念会議」といったものを行います。
前回の合宿に続き、
今回も個人個人の将来・会社の将来、自分がこれからどうしていきたいか・どうなりたいのかといったことを発表して、
それをどうすれば実現できるのかということをみんなで話し合っていきます。
・・・5時間経過後
ということで、写真にはあまり変化がないですが、
一人一人にフォーカスして個人の思想やその背景にある思い、
そしてそれぞれの将来に関してじっくり話し合ってきました。
理念会議が終わった頃には日がすっかり暮れてしまいました。
これからやや遅めの夕食です。
2日目の夕食はBBQ!
「jicca」の方で茨城県産の食材をたくさんご用意して頂いて、みんなでBBQです。
今回のBBQに望むためのチーム編成はこちら
調理部隊
バーベキュー屋の店員
火起こし部隊
おじさんたち
火起こし部隊の後ろで待機です。
そして・・・・
いざBBQ!
普段はこういった機会がなかなか無いので、
みんなでお酒を飲みながら語り合って、貴重な時間を過ごせました。
BBQを堪能し、ほどなくして2日目も終了です。
今日はみんな疲れが出てきたようで、午前12時にはみんな就寝したみたいです。
開発合宿3日目 (最終日)
3日目も天気に恵まれた、気持ちのいい朝を迎えました。
午前9時に起床し、10時にチェックアウトです。
3日目は土浦市街の方で貸会議を借りました。夕方まではこちらで各チーム作業を行い、最後に経過発表です。
お借りしたのは、「ワークヒル土浦」の特別会議室。社内の会議などであれば法人でも利用ができます。
10時~17時の利用で4000円ほどと、なかなかのお手頃価格です。
人数のわりに、とても立派な会議室でした。
こちらで一通り作業をした後、
各チームからの合宿目標の結果発表と振り返りを行いました。
今回の合宿で取り組んでいた、 「ES2015(ES6)の導入」や「Rspecのカバレッジ」に関しては、追ってブログにまとめたいと思いますので、しばしお待ちください。
観光編
JAXA(筑波宇宙センター)に入ってきました!
合宿最終日、会議室で結果発表などを終えた後、
20分ほど車を走らせて茨城県つくば市にある「JAXA 筑波宇宙センター」に行ってきました。
日本の宇宙産業を牽引するJAXA。
アメリカではNASAのスペースシャトルが引退し、SpaceXなどの民間企業へのシフトが進んでいますが、そんな宇宙を相手にする仕事はロマンがあってすごいなあと個人的には思うところです。
最先端の技術たちを駆使して宇宙という過酷な環境に挑むって本当にすごいです。
教育にも最先端の技術をどんどん導入していきたいです。
という訳で、JAXA見学です!
ISSの日本実験棟「きぼう」
中にも入れちゃいます。
宇宙服 (1着あたり10億円するそうです)
興味津々です。
その他にも衛星やロケット、エンジンなどが実物大で見れます。
施設の方(JAXAを引退された方?)に、
宇宙に関して、衛星や衛星に使用している技術など
色々なお話を付きっきりで伺うことができました。
ありがとうございました。
合宿のまとめ
前回に引き続き、今回も有意義な合宿となりました。
今回の合宿での反省点や改善点は次回以降にまた活かしていきたいと思いますが、
これから開発合宿をやろうと考えている方にも、気をつけるポイントなどをあげておこうと思います。
Keep
・メンバーのチームワーク強化に繋がった。
・宿泊代がお手頃。
・旅のお供に温泉は大事。
・ご飯が美味しい。
・宿にネット環境が整っている。
・自然溢れる環境なのでとてもリフレッシュできた。
・近くに娯楽施設がないので、逆に集中できた。
Problem
・床に座って作業するときは座椅子があると良かった。
・作業に当てられる時間が意外と短い。合宿中にやることの選択と集中が大事。
開発合宿のポイント
合宿にあたって気をつけていたことは、
・合宿の目標には数値的な結果が見えやすい目標を。
→ 加えて、合宿の開始と同時に、すぐに作業に取り掛かれる様に準備しておくと時間を無駄にせずに済みます。
→ 開発合宿の醍醐味として合宿中に立てた目標を達成することがとても大事だと思うので、どうしても終わらなそうであれば合宿前にある程度の下準備をしておくといいかと思います。
・お酒は最終日の前夜のみに抑える。
→ ダメになりやすい人は控えましょう。お酒を飲むとせっかくの目標もどうでもよくなっちゃいます。
・ネット環境の確認。
→ wifiの有無はもちろん、速度面なども事前に確認しておくと安心です。
→ もしもの時に、モバイルwifiを各自で持参しておくと何かと便利ですが、圏外になることもしばしばあります。
・電源の確保。
→ 作業する場所で電源が使用できるかはもちろんですが、延長ケーブルを持参すると便利なこともよくあるので、事前に確認しておくと安心です。
・お昼に温泉は入らない。
→ 温泉に入ると気持ちが満たされてせっかくの目標もどうでもよくなっちゃいます。ダメになりやすい人は控えましょう。
・近隣の施設や観光地を調べておく。
→ 特に宿泊施設内もしくは近場にコンビニがあるか確認しておくと安心です。24時間営業ではないコンビニもあるので気をつけておくといいかと思います。
・予定は詰め込み過ぎない。
→ 食事処の予約や会議室の予約など、時間的な余裕を持って対応できる様にしておくといいかと思います。
→ 合宿中にやることも基本的には1~2つに絞ると雑念なく集中できるのではないかと思います。
番外編
懐かしきスマブラ!!
実は遡ること2日目のBBQの後、懐かしきスーパーファミコンと任天堂64が出現!
jiccaの方で貸していただきました!
プロジェクターも用意して頂いて懐かしい気分に浸りつつ、ガチバトル。
猫
jiccaで飼われている猫です。
猫かわいいですね、猫。
いかがでしたでしょうか?
日々の業務では対応できない経営課題や技術課題に取り組むために、新しい技術の試験の場に、新しい事業の創出の場に、開発合宿やってみてもいいかもしれません。
個人的にはリフレッシュもできてES6の導入も無事に進み、温泉に入れて美味しいご飯を食べれていい合宿でした。 これからまた更に事業スピードあげていきたいところです。
We're hiring!!
Cluexではビジネスサイド、エンジニアサイド共にメンバーを募集しています!
気になった方はご連絡ください!!
ビジネスサイド
エンジニア