kintone自体はアプリケーションを非常に簡単に作成できるのですが、そのバックアップ、となると有償の製品を購入するか、あるいは手動で実施する、というのが現状です。
そこで、有償のバックアップとまでは行かなくても、簡易的なバックアップの仕組みを作れないか、試してみました。
ゴール
とりあえず以下の条件をゴールとします。
- バックアップ対象は「フォームの設計」と「データ一式」
- バックアップは自動で定期的に実施される
- 必要であればリストアの仕組みも作る
バックアップのための仕組み
・フォームの設計情報をバックアップ
→フォーム設計情報取得
・データ一式のバックアップ
→第10回 kintone REST APIを利用したレコード取得
これらをAWS Lambda(Python 3)上から呼び出せるように実装します。リストアもjson形式で対応できそうなので、上記のページの通りの結果が得られればバックアップとしては問題なさそうです。
処理対象
こんな感じの備品在庫管理(既成品)を利用します。
実装
前処理
色々と準備が必要なので、最初に実施します。
KINTONE_BASE_URL = os.environ['KINTONE_URL']
KINTONE_FORM_BASE_URL = os.environ['KINTONE_FORM_BASE_URL']
URL = KINTONE_BASE_URL.format(
kintone_domain=os.environ['KINTONE_DOMAIN'],
kintone_app=os.environ['KINTONE_APP']
)
FORM_URL = KINTONE_FORM_BASE_URL.format(
kintone_domain=os.environ['KINTONE_DOMAIN'],
kintone_app=os.environ['KINTONE_APP']
)
HEADERS_KEY = os.environ['KINTONE_HEADERS_KEY']
API_KEY = os.environ['KINTONE_API_KEY']
S3_BUCKET = os.environ['S3_BUCKET']
S3_OBJECT_PREFIX = os.environ['S3_OBJECT_PREFIX']
s3_client = boto3.client('s3')
全レコードの取得
こんな感じでQueryに何も指定しない全件取得を行います。
def get_all_records(headers):
query = u''
response_record = requests.get(URL + query , headers=headers)
return json.loads(response_record.text)
フォーム設計情報取得
フォームは前述のページを参考にこのような実装になります。
def get_form_info(headers):
response_record = requests.get(FORM_URL, headers=headers)
return json.loads(response_record.text)
取得したデータをS3にバックアップとして保持
botoライブラリを利用して、tmpフォルダに一時的に作成したファイルをS3にアップロードします。
def put_data_to_s3(contents):
date = datetime.now()
date_str = date.strftime("%Y%m%d%H%M%S")
tmp_dir = "/tmp/"
tmp_file = S3_OBJECT_PREFIX + "_" + date_str + ".json"
with open(tmp_dir + tmp_file, 'w') as file:
file.write(json.dumps(contents, ensure_ascii=False, indent=4, sort_keys=True, separators=(',', ': ')))
s3_client.upload_file(tmp_dir + tmp_file, S3_BUCKET, tmp_file)
return True
上記を呼び出し側メソッド
今まで作成したきた部品をつなぎ合わせます。それぞれレコード一覧とフォーム設計情報を一つのJSONファイルにまとめる様に実装しています。
def run(event, context):
headers = {HEADERS_KEY: API_KEY}
record_data = get_all_records(headers)
records = record_data['records']
form_data =get_form_info(headers)
forms = form_data['properties']
result = {
"records": records,
"properties": forms
}
return put_data_to_s3(result)
(おまけ)環境変数はステージごとに切り替えるように実装
クラメソさんの記事を参考に、ステージごとに環境変数を切り替えられるようにしています。
service: aws-kintone-backup
provider:
name: aws
runtime: python3.6
region: us-east-1
stage: ${opt:stage, self:custom.defaultStage}
environment:
KINTONE_URL: https://{kintone_domain}/k/v1/records.json?app={kintone_app}
KINTONE_FORM_BASE_URL: https://{kintone_domain}/k/v1/form.json?app={kintone_app}
KINTONE_HEADERS_KEY: X-Cybozu-API-Token
custom:
defaultStage: dev
otherfile:
environment:
dev: ${file(./conf/dev.yml)}
prd: ${file(./conf/prd.yml)}
functions:
run:
handler: handler.run
environment:
KINTONE_DOMAIN: ${self:custom.otherfile.environment.${self:provider.stage}.KINTONE_DOMAIN}
KINTONE_API_KEY: ${self:custom.otherfile.environment.${self:provider.stage}.KINTONE_API_KEY}
KINTONE_APP: ${self:custom.otherfile.environment.${self:provider.stage}.KINTONE_APP}
S3_BUCKET: ${self:custom.otherfile.environment.${self:provider.stage}.S3_BUCKET}
S3_OBJECT_PREFIX: ${self:custom.otherfile.environment.${self:provider.stage}.S3_OBJECT_PREFIX}
KINTONE_DOMAIN: xxxxxx.cybozu.com
KINTONE_API_KEY: XXXXXXXXX
KINTONE_APP: XXX
S3_BUCKET: XXXXXX
S3_OBJECT_PREFIX: XXXXXX
slsコマンドでアップロードをする際に--stage
オプションを指定する必要があります。(デフォルトはdev
)
実行してみる
さて、それぞれ環境変数を指定して実行してみます。無事S3にファイルが出力されました。中身も無事出力されています。(コンテンツが長いからここには載せないけど)
AWS Lambdaで開発しているので、あとはスケジューリングでもすれば自動起動は簡単ですね。
現状の課題
一応できましたが、いくつかすでにわかっている課題があります。
- レコードの一括取得は一度に500件までしかできない。(kintoneの仕様)
- レコードの一括登録は一度に100件までしかできない。(kintoneの仕様)
- S3へアップロードしたファイルはずっと残ってしまう。(手動で削除しに行かないと後々ゴミになる)
- リストアの仕組みがない
この辺を解消するような実装はまた後ほど。
成果物
ここまでの成果物は以下になります。
まとめ
よくあるkintoneアプリケーションのバックアップの一部を自動化することができました。とはいえAPIとしてはプロセス管理やアプリケーションの一般的な設定まで取得するものがあるので、この辺を盛り込むと、どんどんとリッチなバックアップ処理になりそうです。その辺りはまた次にでも。