Google Cloud Functions
ハンズオン
by soundtricker(大橋)
こんな時はありませんか?
2
作ったアプリ内で購入されたらクーポン送りたい
3
クーポン
エラーが起きたらSlackに通知したい
4
エラー内容
サーバーを窓から投げ捨てたい
5
Google Cloud Functions for Firebase
Google Cloud Functions?
7
GCF?
何かあったら
何かしたい
GCPで
を叶えるもの
8
GCF?
何かあったら
何かしたい
GCPで
9
HTTP Requestが来たら
なんかAPIを呼び出したい
GCF?
何かあったら
何かしたい
GCPで
10
Cloud Storageに�ファイルが追加されたら
加工しBigQueryに追加したい
GCF for Firebase?
何かあったら
何かしたい
11
NodeJSで書けるならだいたいなんでも
GCFの作り方
コンソール編
ハンズオン1
12
作り方
13
1. プロジェクト作る
作り方
適当に作って下さい。
14
2. 環境準備
作り方
1. コンソールでCloud Functionsを表示
2. APIを有効化
15
3. コード書く
作り方
1.関数を作成をクリック
16
3. コード書く
作り方
2. 以下のように設定
17
3. コード書く
作り方
3. exports.{名} = function(req, res) {};
HTTPSの場合
exports.helloWorld = function(req, res) {
res.send("Hello from GCF!");
};
18
4. デプロイ
作り方
1. 保存ボタンをクリック ※しばらく待ちます。
19
5. テスト
作り方
2. 画面からやってみる テストタブをクリック
20
5. テスト
作り方
3. 関数をテストをクリック すると関数が実行されて結果が帰ってくる
21
6. テスト2
作り方
22
7. Appendix
作り方
23
GCFの作り方2
CLI編
ハンズオン2
24
作り方
25
1. プロジェクト作る
作り方
適当に作って下さい。
さっきのでもOK
26
2. 環境準備
作り方
※ローカルにgcloudコマンドセットアップ済みならば移行は手元で実施してください。�まだセットアップが終わってない場合はCloud Shellを使ってください。
27
3. コード書く
作り方
1. exports.{名} = function(event, callback) {};
Pub/Subの場合
exports.helloWorld3 = function helloWorld3 (event, callback) {
console.log(`My Cloud Function: ${event.data.message}`);
callback();
};
28
2. 環境準備
作り方
0. gcloudコマンドをインストール&セットアップ
1. betaコマンドを追加
29
$ gcloud components install beta
$ gcloud components update�
3. コード書く
作り方
1. 作業ディレクトリを作成
�
2. ファイルを作成(viじゃなくてもいいです。)
30
$ mkdir ~/function2
$ cd ~/function2
$ vi index.js
4. デプロイ
作り方
1. デプロイ ※結構時間かかります。
31
$ gcloud beta functions deploy helloWorld3 --stage-bucket {さっき作ったやつ} --trigger-topic hello_world�
5. テスト
作り方
1. 以下を叩く
2. ログの確認
32
$ gcloud beta functions call helloWorld3 --data '{"message":"Hello World!"}'
$ gcloud beta functions logs read helloWorld3
6. Appendix
作り方
33
GCF
ライブラリ
34
GCFとライブラリ
{
"dependencies": {
"uuid": "^3.0.1"
}
}
const uuid = require('uuid');
exports.getUuid = function (req, res) {
res.send(uuid.v4());
};
35
GCF
GCSとライブラリ
ハンズオン3
36
GCSとライブラリ
{
"dependencies": {
"@google-cloud/storage": "^1.4.0"
}
}
37
GCSとライブラリ
const storage = require('@google-cloud/storage')();
exports.logSize = function (event, callback) {
const object = event.data;
if (object.resourceState === 'not_exists') {
callback('This is a deletion event.');
return;
;
} else if (!object.name) {
callback('This is a deploy event.');
return;
}
const file = storage.bucket(object.bucket).file(object.name).download(function(err, contents) {
console.log(`${object.name} file size is ${contents.length}`);
callback(null, "success")
});
};
38
GCSとライブラリ
39
Appendix
GCSとライブラリ
40
GCF
GCFとLinux
41
GCFとLinux
42
GCFとLinux
const exec = require('child_process').exec;
const fs = require('fs');
const path = require('path');
const storage = require('@google-cloud/storage')();
exports.blur = (event, callback) => {
const object = event.data;
if (object.resourceState === 'not_exists' || !object.name) {
callback()
return;
}
const tempLocalFilename = `/tmp/${path.parse(file.name).base}`;
return storage.bucket(object.bucket).file(object.name).download({destination: tempLocalFilename})
.catch((err) => {return Promise.reject(err);})
.then(() => {
return new Promise((resolve, reject) => {
exec(`convert ${tempLocalFilename} -channel RGBA -blur 0x24 ${tempLocalFilename}`, {stdio: 'ignore'}, (err, stdout) => {
if (err) {
console.error('Failed to blur image.', err);
reject(err);
} else {
resolve(stdout);
}
});
});
}).then(() => {callback();});
};
43
GCF
GCFとLinux
ハンズオン4
44
GCFとLinux
{
"dependencies": {
"@google-cloud/storage": "^1.4.0",
"ffmpeg-static": "^2.0.0",
"fluent-ffmpeg": "^2.1.2"
}
}
45
GCFとLinux
const ffmpeg = require('fluent-ffmpeg');
const storage = require('@google-cloud/storage')();
const ffmpegStatic = require("ffmpeg-static");
const path = require("path");
exports.animationGif = (event, callback) => {
const object = event.data;
if (object.resourceState === 'not_exists') {
callback('This is a deletion event.');
return;
} else if (!object.name) {
callback('This is a deploy event.');
return;
} else if(!object.name.endsWith("mp4")) {
callback(`Not mp4 file ${object.name}`);
return;
}
console.log(`start convert ${object.name}`);
const bucket = storage.bucket(object.bucket);
const file = bucket.file(object.name);
const tempLocalFilename = `/tmp/${path.parse(file.name).base}`;
const output = tempLocalFilename + ".gif";
// 次のページに続く
46
GCFとLinux
return file.download({destination: tempLocalFilename})
.catch((err) => {
callback(err);
return Promise.reject(err);
})
.then(() => {
// Convert mp4 to animation gif
return new Promise((resolve, reject) => {
ffmpeg(tempLocalFilename)
.outputOptions([
"-an", "-r", "15", "-pix_fmt", "rgb24", "-f", "gif"
])
.setFfmpegPath(ffmpegStatic.path)
.on('end', () => resolve(output))
.on('error', (err) => reject(err))
.save(output);
});
}).then((result) => {
return bucket.upload(result, {destination: `${path.parse(output).base}`, public: true});
}).then(()=> {
callback();
});
};
47
GCFとLinux
48
まとめ
49
まとめ
50
参考資料
51
サーバーを窓から投げ捨てられますね(嘘
52
おまけ
53
Cloud Functions
Local Emulator
54
Local Emulator
55
Local Emulator
56
$ npm install -g @google-cloud/functions-emulator
$ functions start
$ functions deploy helloWorld --trigger-http
Local Emulator
57
$ functions call helloWorld�$ curl http://localhost:8010/YOUR_PROJECT_ID/local/helloWorld
$ functions logs read