AWS Lambda で GCE instances を定期的に監視する

漢だったら AWS Lambda で Google Compute Engine のインスタンス監視したいですよね!

やりましょう!

## node.js コード

参考例として gcloud と async モジュールを使って, 指定時間以上起動している instance を delete するコードをでっち上げます.

AWS Lambda ではファイルを読むなどが出来ない(`node_modules/` ディレクトリに置けば読める?)ので, GCE にアクセスするための credentials 情報を JSON に直接埋め込みます.

```
// gceterminator.js
var secs = 600; // delete instance running larthan this value.
var zones = ['us-east1-b', 'us-east1-c', 'us-east1-d', 'us-central1-a', 'us-central1-b', 'us-central1-c', 'us-central1-f', 'asia-east1-a', 'asia-east1-b', 'asia-east1-c']

var projectId = 'GCE_PROJECT_ID'
var gcloud = require('gcloud');
var async = require('async');

exports.handler = function(event, context) {

  var gce = gcloud.compute({
    projectId: projectId,
    //keyFilename: './keyfile.json'
    credentials: {   
      private_key: "XXXX",
     client_email: "XXXX"
   }
  });

  async.each(zones, function(z, callback) {

    var zone = gce.zone(z);
    console.log('zone = ' + z)

    zone.getVMs(function(err, vms) {
      if (err) {
        console.log("err:" + err);
        callback('err' + err);
      } else {
        console.log('# of vms: ' + vms.length)
        async.each(vms, function(vm, callback) {
          console.log(vm.metadata.creationTimestamp);
          var d = new Date(vm.metadata.creationTimestamp);
          var elapsedMsec = (new Date()) - d;
          var elapsedSec = (elapsedMsec / 1000.0) 
          console.log(elapsedSec);
          if (elapsedSec > secs) {
            console.log("delete " + vm.name);
            vm.delete(function(err, operation, apiResponse) {
            // `operation` is an Operation object that can be used to check the status
            //   // of the request.
              if (err) {
                console.log("vm delete err:" + err);
                callback('vm delete err' + err);
              }
              callback();
            });
          }
          callback();
        }, function(err) {
          callback(err);
        });
      }
    });

  }, function(err) {
    if (err) {
      console.log(err);
      if (context) context.done(err)
    } else {
      console.log("done");
      if (context) context.done(null, 'done')
    }
  });
}
```

`node_modules`, `gceterminator.js` を zip 圧縮して S3 にアップロードします.
(微妙に Lambda のアップロード上限である 10MB を超えるかもしれないので)

## Lambda の設定

ハンドラを `gceterminator.handler` にし, zip ファイルを S3 から取得するようにして Lambda function を定義します.

## Lambda を実行してみる

```
START RequestId:  Version: $LATEST
2015-10-12T16:22:06.088Z		zone = us-east1-b
2015-10-12T16:22:06.111Z		zone = us-east1-c
2015-10-12T16:22:06.112Z		zone = us-east1-d
2015-10-12T16:22:06.113Z		zone = us-central1-a
2015-10-12T16:22:06.169Z		zone = us-central1-b
2015-10-12T16:22:06.170Z		zone = us-central1-c
2015-10-12T16:22:06.170Z		zone = us-central1-f
2015-10-12T16:22:06.170Z		zone = asia-east1-a
2015-10-12T16:22:06.171Z		zone = asia-east1-b
2015-10-12T16:22:06.171Z		zone = asia-east1-c
2015-10-12T16:22:08.712Z		# of vms: 0
2015-10-12T16:22:08.931Z		# of vms: 0
2015-10-12T16:22:09.145Z		# of vms: 0
2015-10-12T16:22:09.191Z		# of vms: 0
2015-10-12T16:22:09.266Z		# of vms: 0
2015-10-12T16:22:09.352Z		# of vms: 0
2015-10-12T16:22:09.416Z		# of vms: 1
2015-10-12T16:22:09.416Z		2015-10-12T09:14:51.579-07:00
2015-10-12T16:22:09.417Z		437.838
2015-10-12T16:22:09.493Z		# of vms: 0
2015-10-12T16:22:09.723Z		# of vms: 0
2015-10-12T16:22:09.754Z		# of vms: 0
2015-10-12T16:22:09.754Z		done
END RequestId: 
REPORT RequestId: 	Duration: 3669.54 ms	Billed Duration: 3700 ms 	Memory Size: 128 MB	Max Memory Used: 57 MB	
```

Voala! 実行できました.

あとはこれを Scheduled event で定期的に実行すれば GCE instances を監視できますね! AWS Lambda 便利ですね, ありがとうございます.

## TODO

* Credentials を lambda code に直接書いていいものなのか? Credentials 情報の管理はどうるするのがよいか?