IFTTTでメールを電話に変換する

とあるメールアドレスにメールが届いたら、ケータイに電話がかかってくるような仕組みをつくる機会がありました。

適当なコードを書いて、AWS Lambdaで動かせばすぐできるのでしょうが、 メンテしたくなかったのでサービス連携サービスIFTTTを使ってみました。

仕様

  • どっかからメールが届く
  • それをトリガーにして電話をかける

前提

  • コードは書かない(重要)
  • 無料にこだわらない

構成

採用サービスは3点

ちなみにIFTTTではなくZapierを使うと、もっと簡単に実現できます。

Gmail

みんな大好きGmail

Twilio

APIで電話やSMSが送れるサービスです。

Twilio for KDDI Web Communications | クラウド電話API

050のアドレスが 108円/月、電話代が 16.2円/分と お手頃な値段で架電環境が構築できます。 ちなみにクレカが必要です。

IFTTT

異なるWebサービスを連携してくれるすごいやつ Twilioは対応していないので、手動で連携レシピをつくる必要があります。

やること

  1. Gmailでアドレス取る
  2. Twilioで電話番号取る
  3. APIで電話してみる(動作確認)
  4. サービス連携

メルアド取得とか電話番号取得とかは悩まないと思うので、3から書きます。

APIで電話してみる(動作確認)

とりあえず公式リファレンス

REST API: Making Calls - Twilio

最低限To、From、Url を渡すと動きます。

curl -X POST https://api.twilio.com/2010-04-01/Accounts/[Account]/Calls \
  -d "To=%2B[To Phone number]" \
  -d "From=%2B[From Phone number]" \
  -d "Url=http://demo.twilio.com/docs/voice.xml"

Account は ACxxxxxx 的なやつで、twilioの画面から見れます。

Toには宛先の電話番号を入れます。
090-1234-5678なら、国際番号81をつけて、"+819012345678"です。
+記号は%2Bにエスケープする必要があるので、最終的には以下のようになります。 "To=%2B819012345678"

FromもToと同様に記載します。 twilioで購入した番号を入力してください。

Urlには、音声内容を指定します。
デフォルトのvoice.xml では、陽気な音楽が流れると思います。

日本語音声の読み上げにも対応しています。
詳しくはこちら。

日本語読み上げ対応。FluentdからTwilioの電話APIを操作する「fluent-plugin-twilio」を使って電話を掛けてみた - Y-Ken Studio

-d オプションで渡す場合は、生成されたURLをさらにURLエンコードする必要があります。
もしくは --url-encoded を使って渡します。

サービス連携

あとで書く

Chefレシピから serverspec のテストコードを自動生成してみた

Chefのレシピ書いた上で、同じようなテストコード書くの面倒だなぁ
誰か書いてくれないかなぁ

って思ってたら、同じように考えている人がいた。
ありがてぇ、ありがてぇ!(涙)

Chef のレシピから serverspec のテストを自動生成する chef-serverspec-handler という gem を作ってみた - DevOps について書くブログ

さっそく入手して自動生成ライフを満喫するんじゃー!!

https://github.com/tily/chef-serverspec-handler

環境とか

CentOS使っているので、そのままだとRubyが1.9系止まり。

$ cat /etc/redhat-release
CentOS release 6.7 (Final)

$ uname -a
Linux vagrant-centos65.vagrantup.com 2.6.32-431.3.1.el6.x86_64 #1 SMP Fri Jan 3 21:39:27 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

rbenvで Ruby 2.0 を入れる

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv install -v 2.0.0-p647
$ rbenv global 2.0.0-p647
$ rbenv rehash

$ ruby -v
ruby 2.0.0p647 (2015-08-18 revision 51631) [x86_64-linux]

入った。

Chef DKのインストール

最新版出てるかもしれないから、確認してね。
https://downloads.chef.io/chef-dk/redhat/

$ wget https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chefdk-0.10.0-1.el6.x86_64.rpm
$ rpm -ivh chefdk-0.10.0-1.el6.x86_64.rpm

cookbook を集約

Berksfileに従って、各種レシピをcookbooksディレクトリに持ってくる。

$ mkdir cookbooks
$ berks vendor cookbooks/

chef-serverspec-handler で spec ファイル生成

$ gem install chef-serverspec-handler
$ chef-solo -c hoge.rb -j huga.json --why-run
$ /tmp/spec/target_recipe/default_spec.rb

上手に焼けましたー!

ファイルの中身はそれぞれこんな感じ。

$ cat hoge.rb
require 'chef-serverspec-handler'

here = File.absolute_path File.dirname(__FILE__)
cookbook_path File.join(here, 'cookbooks')
report_handlers << ChefServerspecHandler.new(output_dir: '/tmp/spec/')
$ cat huga.json
{
  "run_list": [
    "recipe[target_recipe]"
  ]
}

CircleCIから特定AMIでインスタンスを立ててtest-kitchenする

CircleCI便利なんだけど、秘伝のタレな環境をテストするのにちょっとうまくいかない。
具体的には、特定のAMIがあって、そのAMIからLaunchしないと動かない系。

そんな環境捨てて新しくコーダブルな環境にしたり、
Dockerイメージ化して上げちゃうのが良いんだろうけど、
まぁそこはそれ、大人の事情ってやつで。

まえおき

最初は、先人に倣って VagrantAWS driver 使おうと思ったんですけど、
テスト集約ツールとして使っている Kitchen-CI とイヤンな相性だったので、
kitchen-ec2 を使うことに。

あーきてくちゃ

ざっくりとこんなかんじ。正確さはあんまり無い。 f:id:d10gkotatsu:20151201161039p:plain

そーすこーど

github.com

やってること

そんなに難しくないので、コード読めば分かると思う。
ポイントとしては↓のようなかんじ。
- リポジトリには、CircleCIセットアップ用のコードと、AWSインスタンス作成用のコードが入ってる。
- AWS触るための認証情報は、CircleCIのWebコンソールから環境変数として登録する。
- kitchen testコマンドで内部的に呼んでる kitchen createコマンドでAWSインスタンスができる。

おもうところ

私の読解力の問題でドキュメントが読み解けず、ハマることもしばしば。
ssh_keyaws_ssh_key_id の違いとかで1日潰れたり。

とはいえ、最終的には問題なく動いて満足したぜ!(サティスファクション編・完)

ゆるぼ:LVMのStripes設定変更

LVMで組んだ環境がなんか速度でないなーと思ったら、ストライピングされてなかった。

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda1              1.00         0.00        15.92          0         32
dm-0             34.83         0.00       278.61          0        560
sdf              34.33         0.00       278.61          0        560
sdg               0.00         0.00         0.00          0          0

勝手にストライピングされるものと思ってたけど、
どうやら -i オプション付けないとダメらしい。へー。

# lvcreate --help
  lvcreate: Create a logical volume

lvcreate
(snip)
        [-i|--stripes Stripes [-I|--stripesize StripeSize]]

じゃあ変更すればいっか、と思ったけど、後から変更する方法がワカラナイ。
lvextend にも同じようなオプションがあるけど、怒られるだけで設定が変わらない。
ぐぬぬ

Docker Logging Driver の fluentd プラグインを使って maillog をホストに持って来・・・たかった

Dockerでメールサーバー作ったけど、メールログがローテートされなかった。
原因はシンプルで、cronが入ってなくてローテートが動いていなかった。

普通ならパッケージ入れてはい終了、なんだけど
Dockerの Logging Driver に fluentdが追加されたとか聞いたんですよ。

/var/log/maillog の内容をリモートに飛ばせるなら夢がひろがりんぐ
とか思って、Loggin Driver とか fluentd とかよく知らないままにとりかかる。


ホストOSは Amazon Linux バージョンは 2015.03

$ cat /etc/system-release
Amazon Linux AMI release 2015.03

環境構築は先人にならう。感謝。
DockerのFluentd Logging Driverを試してみる | Developers.IO

Docker Logging Driver の fluentd のドキュメント。
Fluentd logging driver


ここで気が付いたけど、source が stdoutstderr しか無いのよね。
ログファイルを読んで内容をリモートに送るとか、そんなことはできない。

じゃあ諦めて、コンテナにcron入れるか、fluentd入れて飛ばそう!
と思うじゃん?
この時すでに4時間ぐらい格闘していたので、諦めるには惜しくなったのです。

そしてメールログの内容を標準出力に出せば、dockerが拾ってくれるぞ!
という電波を受信して、さっそく実行。

syslogのmailファシリティを標準出力に。

# vim /etc/rsyslog.conf
mail.*                                                  -/var/log/maillog
↓
mail.*                                                  /dev/console

とりあえずコンテナの標準出力を全部ファイルに出力

# cat /etc/td-agent/td-agent.conf
<source>
  type forward
</source>
<match docker.**>
  type file
  path /var/log/td-agent/docker
</match>

接続してみると、無事にログに出力されました。

# telnet [docker container] 25

----
2015-09-04T02:35:06+00:00       docker.c00f3fb20b3e     {
    "container_name":"/test",
    "source":"stdout","log":"\u001B[?1049h\u001B[?1h\u001B=\rSep  4 02:35:01 test postfix/smtpd[179]: connect from localhost[::1]\r",
    "container_id":"c00f3fb20b3e9c068c062ac563d3bf35182ad64cee303955af9aa49358d3db5c"
}

あとはプラグインでログを整形してから出力すれば、きちんとしたものが見れそう。


Logging Driverを使ってみた感想としては、ログを標準出力に書くアプリケーションなら超絶便利そう。

既成品なら、標準出力/エラー出力だけしか取れないので微妙。
素直にホストをマウントしてローテートをホストに任せるか、コンテナにfluentdとcronを入れましょう。

Mac上のVirtualBoxにFluentd(td-agent)を入れる

コマンドひとつで好き勝手にマシンが作れるのは便利だけれど、
いちいちリモートにログインしてログを見るのがどうにも面倒くさい・・・。

ログをホストに持ってきたら、楽ちんじゃん!!
ということで、仮想マシン作成時にfluentd(td-agent)を入れてログを飛ばすことにしました。
開発機のMacに、VagrantVirtualBoxを入れています。 f:id:d10gkotatsu:20150805175453p:plain
 

fluentdインストール

クイックスタードガイドによると、色々とインストール方法があるみたいですが、
今回は何度も潰して建てる環境なので、chefでインストールが楽ですかね。
Quickstart Guide | Fluentd

 

Berksfileでtd-agentを落としてくる。

$ echo 'cookbook "td-agent"' >> Berksfile
$ berks install

ついでに knifhプラグインの chef-td-agent も持ってくる。

$ gem install knife-github-cookbooks
$ knife cookbook github install treasure-data/chef-td-agent

 

Vagrant仮想マシン起動時にインストールされるよう追加。

$ cat Vagrantfile
    (略)
config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = "./cookbooks"
    chef.run_list = %w[
        recipe[td-agent]
    ]
end
(略)

以上でインストール完了。

vargrant up で起動。勝手に追加してくれます。

ゲストのtd-agent

ゲストにログインして、ローカルのファイルから、ローカルのファイルへ転送をしてみます。
設定は以下の通り。

# cat /etc/td-agent/td-agent.conf
<source>
    type tail
    format none
    path /var/log/example
    tag example.hoge
</source>

<match example.*>
    type file
    path /var/log/td-agent/example
</match>

td-agentユーザーで動作するようなので、パーミッションにはご注意ください。
あとは出力先をゲストの/vagrant/にすれば終了です。 vagrantのおかげで、ホストとのファイル共有も楽ちん。

fluentd と td-agent

そういやfluentdとtd-agentの関係がよく分かりませんでした。
古い記事だと、fluentdの安定版がtd-agentみたいな事が書いてましたけど・・・

fluentdの公式で、td-agentのインストール手順しか書いていないってことは、
fluentdの実装が td-agent になったって認識でいいんですかね?