定期実行でデータの同期を実現するスマートな方法 その2〜AWS Lambda 編〜

著者名: クローバ株式会社 (External link) 門屋 亮 (External link)

目次

caution
警告

この記事では ver. 0.x.x の cli-kintone を使って説明しています。
ver.1.0.0 以降の cli-kintone の使い方は、次のページを参照してください。
kintone コマンドラインツール(cli-kintone)

はじめに

こんにちは、クローバの門屋です。
以前、次の記事で異なるドメイン間の kintone データを同期する方法について書かせていただきました。
定期実行でデータの同期を実現するスマートな方法 その1〜cli-kintone編〜

今回は、AWS Lambda を使ってサーバーレスで kintone の同期を実現する方法を紹介してみたいと思います。

なにがうれしいか

定期実行でデータの同期を実現するスマートな方法 その1〜cli-kintone編〜 では、常時稼働するサーバーで cron などのスケジューリングサービスを使用して定期実行する前提でした。
しかしわざわざそのために常時稼働のサーバーを用意するのが難しい場合もあると思います。
AWS Lambda を使えば、サーバーを用意しなくても定期実行ができます。

おさらい

同期するアプリは 定期実行でデータの同期を実現するスマートな方法 その1〜cli-kintone編〜 を参考に準備してください。
作成したスクリプトは以下の 2 つでした。

conv_csv.py

cli-kintone によって生成された CSV を加工するスクリプトです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
import csv
import sys

argvs = sys.argv
argc = len(argvs)

reader = csv.reader(sys.stdin)
out = csv.writer(sys.stdout)
header = []
try:
  header = next(reader)
except StopIteration:
  quit
if (argc > 1):
  for i, fld in enumerate(header):
    if (fld == argvs[1]):
      header[i] = '*%s' % fld
out.writerow(header[2:])

for row in reader:
  out.writerow(row[2:])

copy2kintone

全体の処理を行うシェルスクリプトです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
cd `dirname $0`

# 定数の定義ここから
APP_ID_A=998
DOMAIN_A="domaina"
API_TOKEN_A="ELH834tmgivQFyk4ZYmyyVmJPZgrld9VqSnP3HtU"
APP_ID_B=999
DOMAIN_B="domainb"
API_TOKEN_B="8Nt48J7iwf2evOjxKWIMlX3FYK89hBcgnUWzAi70"
KEY_FIELD="key_field"
# ここまで

DATE_TO=$(date +"%Y-%m-%d")
# For GNU
DATE_FROM=$(date -d '1 day ago' +"%Y-%m-%d")

rm -f new_records.csv
rm -f updated_records.csv

./cli-kintone -d $DOMAIN_A -a $APP_ID_A -t $API_TOKEN_A -q "作成日時 >= \"${DATE_FROM}\" and 作成日時 < \"${DATE_TO}\"" | python conv_csv.py > new_records.csv
./cli-kintone -d $DOMAIN_A -a $APP_ID_A -t $API_TOKEN_A -q "作成日時 < \"${DATE_FROM}\" and 更新日時 >= \"${DATE_FROM}\" and 更新日時 < \"${DATE_TO}\"" | python conv_csv.py ${KEY_FIELD} > updated_records.csv
./cli-kintone -d $DOMAIN_B -a $APP_ID_B -t $API_TOKEN_B -f new_records.csv
./cli-kintone -d $DOMAIN_B -a $APP_ID_B -t $API_TOKEN_B -f updated_records.csv

Lambda 上で動作するスクリプトの作成

今回はさらに、Lambda 上でこれらを動作させるためのスクリプトを作成します。
今回は Node.js でスクリプトを記述することにします。

index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
'use strict';

const exec = require('child_process').exec;
const cmd = 'bash -c "cp cli-kintone conv_csv.py copy2kintone /tmp; chmod 755 /tmp/cli-kintone; chmod 755 /tmp/copy2kintone; cd /tmp; ./copy2kintone"';

exports.handler = (event, context, callback) => {
  const child = exec(cmd, (error) => {
    // プロセスの終了
    callback(error, 'Process complete!');
  });

  // ログの出力
  child.stdout.on('data', console.log);
  child.stderr.on('data', console.error);
};

ファイルを zip にまとめる

プログラムを Lambda 上で動かすには、ファイルを zip にまとめる必要があります。
以下にその手順を説明します。

Linux 版 cli-kintone をダウンロードする

AWS Lambda は Linux で動作しますので、 Github (External link) から最新の cli-kintone(linux-x64.zip)をダウンロードして解凍します。

ファイルをすべて同じフォルダーにコピーする

ファイル名 説明
cli-kintone kintone コマンドラインツール
copy2kintone 全体の処理を行うシェルスクリプト
conv_csv.py CSVを加工するスクリプト
index.js Lambdaのメイン関数

zip で圧縮する

ここで注意しないといけないのは、フォルダーを圧縮するのではなくファイル単位で圧縮しないといけないということです。
Mac や Linux、Windows の cygwin 環境などでは以下のコマンドで圧縮できます。
Windows のエクスプローラーの場合は、フォルダーではなくファイルを個別に複数選択して、右クリックで圧縮するとよいようです。

1
zip -r kintone-lambda.zip index.js cli-kintone conv_csv.py copy2kintone

Lambda 関数を作成する

AWS の Web コンソールから、Lambda 関数を作成します。

Blueprint の選択

「Create a Lambda Function」ボタンを押して関数を作成します。
最初に使用するランタイム言語と Blueprint を選択します。
ランタイム言語は Node.js 4.3 とします。
Blueprint は何を選んでもかまいません。

環境設定

以下のように環境を設定します。

設定 説明
Triggers あとで設定するのでいったん空欄にしておきます
Name cron_clikintone
Runtime Node.js 4.3
Code entry type Upload a .ZIP file
Handler index.handler
Role Lambda用のロールがなければ新規作成してください
Memory 128MB
Timeout 5 min

Code entry type のところで Zip ファイルを選択すると、アップロードボタンが表示されますので、さきほど作成した zip ファイルをアップロードします。

設定が終わったら、「Create Function」をクリックして作成を完了します。

テスト

「Test」ボタンをクリックすると動作確認を行うことができます。
デフォルトの Hello World イベントで問題ありません。
実行が正常終了すると、「Execution result: succeeded」と表示されます。

自動実行の設定

「Triggers」タブから、「Add trigger」をクリックしてトリガーを追加します。
イベントソースとして、「CloudWatch Events - Schedule」を選択します。

設定 説明
Rule name ルールごとに一意の名前をつけます
Schedule expression cron(0 17 * * ? *)

これで、毎日午前 2 時(日本時間)に、同期処理が実行されるようになります。

Schedule expression の記述方法については AWS Lambda デベロッパーガイド「 rate または cron を使用する式をスケジュールする (External link) 」を参考にしてください。

おわりに

いかがだったでしょうか。
ちょっと複雑だったかもしれませんが、サーバーを自前で用意しなくて済むのは大きな利点ではないでしょうか。
また、S3 など他の AWS サービスと組み合わせることで、たとえば S3 にデータがアップロードされたタイミングでそのデータを同期するといったようなことも可能です。
Lambda を使うと OS などの管理も不要なため、アプリケーションの運用だけに集中できます。
cli-kintone と組み合わせることでコードの記述も最小限に抑えられますので、ぜひうまく活用してみてください。