Oracle Functionsに関するメモ

　オープンソースで開発されたFn ProjectをもとにしたOCIのサービス"OracleFunctions"。
AWS Lambda、Cloud Functionsのようにサーバレスな処理を実装でき、かつオープンソースベースのため非常に拡張性があり、色んな使い方ができるのではと思っています。

 - 情報  
[2018年末のアナウンス※Oracle Cloud Infrastructure Blogより
](https://blogs.oracle.com/cloud-infrastructure/announcing-oracle-functions)   
[Oracle Innovation Summit Tokyo 2018の記事 ※EnterpriseZineより](https://enterprisezine.jp/dbonline/detail/11026)  
[Oracle Cloudのサーバレス「Oracle Functions」が正式リリース。Azureのイベントとの連携も可能](https://www.publickey1.jp/blog/19/oracle_cloudoracle_functionsazure.html) ※PublicKeyより

　そのOracle Functionsについて、検証した際のメモをまとめました。
Oracle Functions自体は現在も開発中のようで私も気づかないうちに機能がアップデートされています。
 本記事の内容が古くなる可能性もございますのでその点ご了承ください。

Oracle FunctionsはOCI computeダッシュボード上 左メニュー > Developer Servicies > Functions より選択できます。
<img width="412" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/12c1e7f4-7891-8f52-a516-f73e89d0a599.png">

## Fn Project,OracleFunctionsについて
・Fn Projectとは、Oracleがオープンソース化した、コンテナネイティブなサーバレスプラットフォーム。
([Fn Project公式HP](https://fnproject.io/), [Fn Project Git](https://github.com/fnproject))。
・サーバレスと言いつつ、関数を作成するための開発環境用サーバは必要。サーバはローカルの仮想環境でも実装可能。
・Oracle Functionsを操作するときには、fn cli を使用する。
・Oracle Functionsを動かすには、oci cli、docker、fn cliのインストールが必要。
・fn cli では、様々な Fn 環境を扱うことが出来る。OracleFunctions、オンプレ、AWSの環境など。
・扱う環境を切り替えるために、fn cli 上で context を設定する。
・開発環境で関数を作成。fn deployコマンドで、その関数をDockerImageとしてBuildし、OCIRと呼ばれるOCI側のRegistoryサービスにPushする。
　そのDockerImageを使用して、OCI側の Fn ServerでFunctionとして実行される。
　※開発環境でファンクションを編集したらfn deployでデプロイし直す。
・サポートされている言語(fn initのオプションで現在選択できるもの)
go, java, java11, java8, kotlin, node, python, python3.6, python3.7.1, ruby
・CRONのように定期実行する機能が今後追加されるよう
・1つの関数実行のメモリ割り当て制限が1024MB
・1つの関数の実行時間の制限は2分(ここは正直もう少し長くしてほしい。)

## 料金について
　月200万リクエスト無料です。それ以降100万リクエストごとに0.2ドル。
また実行時間、リソースの使用についての課金もAWSより安価です。そのため使い方によってはほぼ無料で使えます。
　Oracle Functions自体その安さがメリットの一つでもあります。

## 

## Oracle Functionsセットアップについて
以下手順を参照してください。
[・Oracle Functionsセットアップ](https://qiita.com/y-araki-qiita/items/d1ed0551d8943adc3bb5)

## 開発環境で作成するソースコードについて
・基本的なシンプルな構成例(Goの場合)
├Dockerfile (独自のDockerImageを作成するもの。無くてもいいが作成時に値渡したり、何かインストールしたり規定できる。)
├func.yaml (fnの定義ファイル。)
├Gopkg.toml (Goで使用するパッケージ、依存関係の定義。fnproject/fdk-go使うよというぐらい。)
└func.go (関数を実行するメインのファイル)

こちらの記事は上記構成で作成しています。
[・Oracle FunctionsでOCIインスタンスの起動・停止・再起動](https://qiita.com/y-araki-qiita/items/28a60c63170d0d5182e6)

## 関数実行の方法
・Fn開発環境にてfn invokeコマンドを実行
・イベント実行
　OCIコンソール上"Events"より、OCIリソースに何らかのイベントが発生した際のアクションとして、ファンクションを実行できます。
<img width="458" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/581754d0-1e21-dddb-3d4d-018cfe17ccae.png">

・httpリクエストのトリガー
などなど。こちらは今後cronのように実行できる機能も追加されるとのこと。

## 関数実行に必要な、クレデンシャルなど変数設定方法
設定方法は複数ある。例えば、
・fn create app コマンドのオプションで設定
・fn config コマンドで設定
・fn invoke コマンド時にパイプで渡す。
　例) echo -n '{"CompartmentIDFilter":"コンパートメントID"} | fn invoke アプリケーション名 関数名
・func.yamlに記載
・Dockerfileに記載
※パイプで渡す方法以外は開発サーバ側でクレデンシャル情報をずっと持っておく必要はない(極端な話開発サーバが壊れてもOracleFunctions側にデプロイすれば実行可能)。

## OCI SDK使用する際に必要な値について
OCI SDKを使用する場合、以下クレデンシャルの変数設定する(もちろん変数名はそのプログラムにより変わる)
・PRIVATE_KEY_NAME
・TENANT_OCID
・USER_OCID
・REGION
・FINGERPRINT
・COMPARTMENT_ID
・PASSPHRASE ※秘密鍵に設定していない場合必要ない

秘密鍵の情報を渡す際、fn deployコマンドに --build-arg PRIVATE_KEY_NAME=oci_api_key.pem の
オプションつけて、コンテナイメージ作成時に渡す。ただ一時的にchmod 644 しないとデプロイ時エラーになる。

ただ秘密鍵を渡すのはセキュリティ的に不安が残るため、インスタンスプリンシパルを使う方法があるそう。

## Functionsに値を渡して実行する方法
こちらは開発サーバ内で関数を実行する場合です。
もちろんプログラム内でjsonファイルをインポートしたりすれば渡す必要はないです。
■ コマンドによる出力をパイプで渡す。
例) echo -n '{"name": "test.txt", "bucketName":"test-bucket"}' | fn invoke fn-object-store-app get

※DEBUG=1とつけるとデバッグモード
例) echo -n '{"CompartmentIDFilter":"ocid1.compartment.oc1..aaaaaaaa..."}' | DEBUG=1 fn invoke fn-compute-app list

※jsonファイルを用意して渡す。
例) cat db-information.json | fn invoke fn-db-event-app start-autonomous-db

※文字コード変換バージョン。
例) iconv -f UTF-8 -t ISO-2022-JP mail.json | fn invoke fn-email-app sendemail

■ fn invokeをパイプで繋ぐ。

## Oracle Functionsで出来ること
Oracle社のお二人がGitのリポジトリに上げているサンプルがとんでもなく参考になります。
一人の方とお会いしたことがあるのですが、一般公開されているので紹介してしまいます。
[・Abhishek GuptaさんのGit](https://github.com/abhirockzz)
[・Shaun SmithさんのGit](https://github.com/shaunsmith)

また自分が検証、作成した内容のリンクを以下に記載していきます。
[・Oracle FunctionsでAPEXのRestful Serviceと連携](https://qiita.com/y-araki-qiita/items/03e67f5bca570c526a7c)
[・Oracle FunctionsでTensorFlowによる画像分類](https://qiita.com/y-araki-qiita/items/fefebb7e7b20d8573095)
[・Oracle FunctionsでEmail Deliveryと連携しメール送信](https://qiita.com/y-araki-qiita/items/5a580bb739b37198300d)
[・Oracle FunctionsでObject Storage操作 (テキストを格納・取得+テキストをPDFに変換)](https://qiita.com/y-araki-qiita/items/e55bfe111794feda7716)
[・Fn Project - Fn Server構築 (Oracle Linux7.6)](https://qiita.com/y-araki-qiita/items/e11369243723792d1a6e)
[・Oracle FunctionsでOCI Go SDKを使いインスタンス操作](https://qiita.com/y-araki-qiita/items/c927aea9e743a4468c61)

## 検証した感想
　OracleFunctions単体で実行することはもちろん出来ますし、Fn ProjectのFn Server、Linuxコマンドやスクリプトとの連携、はたまたAWS Lambda、Azureのイベント機能など他クラウドのサービスとも連携できるようです。
今後実例を記事にしていければと思います。