GAS+S3を使ってサービス運営向け設定ツールを超絶簡単に作成する方法


![スクリーンショット 2014-12-04 19.25.25.png](https://qiita-image-store.s3.amazonaws.com/0/35671/9648f37f-b9f1-eefa-2cdd-89f2c8157eae.png "スクリーンショット 2014-12-04 19.25.25.png")
# はじめに

Webサービスを開発していくときに、以外と手間がかかるのが"管理ツール"と呼ばれる運営者側がサービスの設定を行う機能です。

広告やバナーの設定やタイアップ・コラボといった短期的な案件、ちょっとしたABテストの条件、新機能の段階的リリースなどなど毎回DB作成をして、一人か二人の担当者のためのツールを作成するのは非常に手間ですし、勿体無い。

かといって、設定ファイルをエンジニアが書き換えてデプロイするのも作業の割り込みが多くなってしまい生産性を低くしてしまいます。

そんなわけで、ちょっとした設定ツールをさくっと作りたいなというときは以外と多いわけです。

今回は、Google DocsとGoogle Apps Script(GAS)を利用して、簡単に設定ツールを作成する方法を紹介します。

# 作成イメージ


![G8uAatqVUN-2.gif](https://qiita-image-store.s3.amazonaws.com/0/35671/928895b9-832d-7c0a-e40d-fb55b0123ae9.gif "G8uAatqVUN-2.gif")

Google Docsで上記のような設定項目を並べたSpreadSheetを作成します。今回は障害時に一部機能を停止して、メンテナンスモードにするためのフラグ管理ツールをイメージしてみました。

このシートを書き換えて、JSONとしてS3に保存するというマクロを記述しておき、変更時にはそれを実行するというイメージです。

![スクリーンショット 2014-12-04 19.25.50.png](https://qiita-image-store.s3.amazonaws.com/0/35671/278a9a71-b49c-140c-ef32-a7491135b877.png "スクリーンショット 2014-12-04 19.25.50.png")

```json:S3に出力されるjsonファイル（{{ドキュメント名}}-{{シート名}}.json）
[{"name":"payment","status":true,"description":"決済ロジック"},{"name":"signup","status":false,"description":"新規登録"},{"name":"siginin","status":false,"description":"サインイン"},{"name":"like","status":true,"description":"イイネ機能"}]
```

一行目をField名として、JSONを生成します。

# アプリケーション側

アプリケーション側では、一定サイクルでS3上のファイルを同期するようにして、そのJSONをアプリケーションに組み込みます。

あるいは、S3の代わりにDynamoDBに保存するというのもいいでしょう。いずれにせよ、アプリケーションがスケールしてもあまりパフォーマンスに影響の出ない方法で、このJSONにアクセスできるようにします。

# 権限管理

管理ツールにアクセスできる人をコントロールしなければならないケースの場合、IAMでリソースへのアクセス権の管理とGoogle Docsの共有設定の管理をしておけば、自由に会社内での権限付与を行うことができるます。


# ソースコード

そのうち、Add-onとして公開したい。Add-onの公開には手間がかかりそうだったので、一旦ソースコードと手順をここに書いておきます。

+ 管理ツールにしたいSpreadSheetを開く
+ 次のソースコードをツール->スクリプトエディタにコピペし
+ リソース->ライブラリ -> 「MB4837UymyETXyn8cv3fNXZc9ncYTrHL9」で検索しS3を追加
+ リソース->現在のプロジェクトのトリガー->起動時にonInitを設定
+ SpreadSheetに戻り、S3メニュー->AWS認可設定からKEYとSECRETを設定
+ S3メニュー->Bucket設定から、Bucket名を設定

新しくconfigを追加したい場合は、sheetを作成する。

```javascript:s3-json-dumper.gs
// MB4837UymyETXyn8cv3fNXZc9ncYTrHL9 をライブラリ登録しS3を追加
function $sheet(){
  return SpreadsheetApp.getActiveSheet();
}

function $sp(){
  return SpreadsheetApp.getActiveSpreadsheet()
}


function onInit(){
  var sp = $sp();
  sp.addMenu("S3メニュー", [
    {name : "S3に保存",functionName:"saveToS3"},
    {name : "保存先Bucket",functionName:"setBucket"},
    {name : "AWS認可設定",functionName:"setAuth"}
  ])
}

function saveToS3(){
  var dp     = PropertiesService.getDocumentProperties();
  var key    = dp.getProperty("AWS_KEY");
  var secret = dp.getProperty("AWS_SECRET");
  var bucket = dp.getProperty("BUCKET");
  
  var s3 = S3.getInstance(key, secret);  
  var spTitle = $sp().getName();
  var sheets = $sp().getSheets();
  Logger.log(sheets);
  for (var i=0,l=sheets.length;i<l;i++){
    s3.putObject(bucket, [spTitle+"-"+sheets[i].getName(),"json"].join("."),readSheetAsObject(sheets[i]));
  }
}


function setAuth(){
  var dp = PropertiesService.getDocumentProperties();
  
  var key    = Browser.inputBox('Enter AWS KEY', Browser.Buttons.OK_CANCEL);
  var secret = Browser.inputBox('Enter AWS SECRET', Browser.Buttons.OK_CANCEL);
  
  dp.setProperty("AWS_KEY", key);
  dp.setProperty("AWS_SECRET", secret);
}

function setBucket(){
  var dp = PropertiesService.getDocumentProperties();
  var bucket = Browser.inputBox('Enter Bucket Name', Browser.Buttons.OK_CANCEL);
  dp.setProperty("BUCKET", bucket);
}

function readSheetAsObject(sheet) {
  var rows = sheet.getDataRange();
  var numRows = rows.getNumRows();
  var values = rows.getValues();
  var fields = values.shift();
  var r = values.map(function(e){
    var o = {};    
    fields.forEach(function(f,i){
      o[f] = e[i];
    });
    return o;
  });
  return r;
}

```