Oracle FunctionsでObject Storage操作(テキストを格納・取得+テキストをPDFに変換)

Oracle Functionsを使ってObject Storageのオブジェクトをバケットに入れたり、オブジェクトをリストしたり、
特定のオブジェクトの内容を取得する操作を実行します。
その後バケットに入れたテキストファイルをPDFに変換する方法も記載します。

OracleFunctionsって？という方は[こちら](https://qiita.com/y-araki-qiita/items/f73f815ea60a93978cac) 。

# Oracle FunctionsでObject Storage操作

## 設定方法について
設定方法は2通りあります。
1.クレデンシャル情報(ユーザOCIDや公開鍵のフィンガープリントなど)を設定して、Object Storageを操作。
2.Dynamic Groupやポリシーを設定し、Object Storageの特定のバケットに操作権限を与える。

現在はセキュリティ面も考え、2の方法が推奨されているようなので、そちらで設定したほうがよいです。
今回はObject Storage内のテキスト操作は2の方法、テキストをPDF変換は1の方法でやります。

## 前提
特定のコンパートメントにバケットが作成されていること(作成方法については割愛します)。
Oracle Functions開発、実行環境が構築されていること。
　⇒[・Oracle Functionsセットアップ](https://qiita.com/y-araki-qiita/items/d1ed0551d8943adc3bb5)

## ソースコードを用意
今回はこちらを使用します。
https://github.com/abhirockzz/oracle-functions-oci-object-store

```
クローン
git clone https://github.com/abhirockzz/oracle-functions-oci-object-store.git
移動
cd oracle-functions-oci-object-store
```

## アプリケーション作成
```
fn create app --annotation oracle.com/oci/subnetIds='["Oracle Functions用に作成したサブネットOCID"]' --config NAMESPACE=ネームスペース fn-object-store-app
```
※ネームスペースの確認方法
ネームスペースの説明については[こちら](https://docs.oracle.com/cd/E97706_01/Content/Object/Tasks/understandingnamespaces.htm)をご確認ください。
確認方法は、OCIコンソールの右上「人マーク」をクリックしてください。
![Inkedキャプチャ_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/6593594c-a43f-019e-746f-f9d9f14a734c.jpeg)
左下にある「Object Storage Namespace」に記載されているのがObject Storageのネームスペースです。

## デプロイ
```
fn -v deploy --app fn-object-store-app --all
※一度にまとめて関数をデプロイしたい場合は、--allを使用します。
```

## Object Storage操作に必要なポリシーの設定
### リスト機能の設定 (list)
まず開発環境で以下コマンドを実行します。

```
fn inspect fn fn-object-store-app listobjects id
```
するとファンクションIDといわれるものが表示されます。

### Dynamic Groupの作成
Identity > Dynamic Groups > Create Dynamic Groupより
以下入力し作成します。
<img width="458" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/f38eed5e-ad52-3606-d057-8d3bf9f088bb.png">
NAMEとDESCRIPTION: fn-obj-store-list-dg (任意)
RULE1: ALL {resource.id = '先ほど表示されたファンクションID'}
例) ALL {resource.id = 'ocid1.fnfunc.oc1.phx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'}
入力後、Create Dynamic Groupをクリックします。

## ポリシー作成
Identity > Dynamic Groups > Create Dynamic Groupより
以下入力し作成します。
<img width="465" alt="キャプチャ2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/8bf6c7f9-dd0f-ef92-3dbe-667e12699d77.png">
NAMEとDESCRIPTION: fn-policy (任意)
STATEMENT:
Allow dynamic-group fn-obj-store-list-dg to read objects in compartment コンパートメント名 where all{target.bucket.name='バケット名'}
※今回のために作成したバケット名と、そのバケットが存在するコンパートメント名を入力します。
入力後、Createをクリックします。

オブジェクト取得(get)と、オブジェクト配置(put)もこれと全く同じ要領で設定します。
２つは簡単に入力項目だけ記載します。

### オブジェクト取得機能の設定 (get)
## ファンクションID確認
```
fn inspect fn fn-object-store-app getobject id
```
### Dynamic Groupの作成
Identity > Dynamic Groups > Create Dynamic Groupより
NAMEとDESCRIPTION:: fn-obj-store-get-dg
RULE1： ALL {resource.id = 'getobject id で表示されたファンクションID'}

## ポリシー作成
ポリシーの一覧からfn-policy > Add Policy Statementより
以下２つを追加します。

```
allow dynamic-group fn-obj-store-get-dg to read buckets in compartment コンパートメント名
allow dynamic-group fn-obj-store-get-dg to read objects in compartment コンパートメント名 where all{target.bucket.name='バケット名'}
```

### オブジェクト取得機能の設定 (get)
## ファンクションID確認
```
fn inspect fn fn-object-store-app getobject id
```
### Dynamic Groupの作成
Identity > Dynamic Groups > Create Dynamic Groupより
Dynamic Group名: fn-obj-store-get-dg
RULE1： ALL {resource.id = 'getobject id で表示されたファンクションID'}

## ポリシー作成
ポリシーの一覧からfn-policy > Add Policy Statementより
以下２つを追加します。

```
allow dynamic-group fn-obj-store-get-dg to read buckets in compartment コンパートメント名
allow dynamic-group fn-obj-store-get-dg to read objects in compartment コンパートメント名 where all{target.bucket.name='バケット名'}
```
### オブジェクト配置機能の設定 (put)
## ファンクションID確認
```
fn inspect fn fn-object-store-app putobject id
```
### Dynamic Groupの作成
Identity > Dynamic Groups > Create Dynamic Groupより
NAMEとDESCRIPTION:: fn-obj-store-put-dg
RULE1： ALL {resource.id = 'putobject id で表示されたファンクションID'}

## ポリシー作成
ポリシーの一覧からfn-policy > Add Policy Statementより
以下２つを追加します。

```
Allow dynamic-group fn-obj-store-put-dg to read buckets in compartment コンパートメント名
Allow dynamic-group fn-obj-store-put-dg to manage objects in compartment fn-compartment where any {request.permission='OBJECT_CREATE', request.permission='OBJECT_INSPECT'}```
```

ひとつのDynamic Groupに複数のルールも設定できるのですが、今回はわかりやすいように分けました。

## Object Storage操作実行
### オブジェクトを格納(put)
```
例)
echo -n '{"name": "<filename>", "bucketName":"<BUCKET_NAME>", "content": "<TEXT_CONTENT>"}' | fn invoke fn-object-store-app putobject

実際にやってみます(自分検証用にaraki-bucketというバケットを作成しています)。
echo -n '{"name": "test.txt", "bucketName":"araki-bucket", "content": "Ahex twin - Richard D. James Album"}' | fn invoke fn-object-store-app putobject
最初は結構時間がかかるのでトイレにでも行ってください。戻ってくるとSuccessfully と表示されています。

もうひとつやってみます。
echo -n '{"name": "test2.txt", "bucketName":"araki-bucket", "content": "Ahex twin - SELECTED AMBIENT WORKS 85-92"}' | fn invoke fn-object-store-app putobject
今回は割とすぐにSuccessfully と表示されます。
```

### オブジェクトを取得(get)
```
例)
echo -n '{"name": "<filename>", "bucketName":"<BUCKET_NAME>"}' | fn invoke fn-object-store-app getobject

実際にやってみます。
echo -n '{"name": "test.txt", "bucketName":"araki-bucket"}' | fn invoke fn-object-store-app getobject

putしたテキストの内容が表示されます。
Ahex twin - SELECTED AMBIENT WORKS 85-92
```

### オブジェクトの表示(list)
```
例)
echo -n '<BUCKET_NAME>' | fn invoke fn-object-store-app listobjects

echo -n 'araki-bucket' | fn invoke fn-object-store-app listobjects
以下のようにファイル名が表示されます。
["test.txt","test2.txt"]
```

何かをトリガーにObject Storageの操作を発動するという使い方が多いと思いますので、
他のファンクションと連携したり、ソースコードを編集して他の機能も追加するとよいでしょう。

# Object Storage内のテキストをPDFに変換
次はバケット内に格納したテキストファイルをPDFに変換してみます(変換後も元のファイルは残ります)。

## ソースコードを用意
今回はこちらを使用します。
https://github.com/abhirockzz/fn-text2pdf
実はこちらの手順通りやってもうまくいかないのですが、Oracle Functionsをずっとやってると大体わかります。

```
クローン
git clone https://github.com/abhirockzz/fn-text2pdf.git
移動
cd fn-text2pdf
```
## OCI秘密鍵の用意
今回は関数を動かすためにクレデンシャルが必要なため、その方法でやってみます。

```
OCI秘密鍵をコピー ※鍵名がoci_api_key.pemの場合。
cp ~/.oci/oci_api_key.pem .
権限変更 ※しないとデプロイエラーになります。ただデプロイ後削除します。
chmod 644 oci_api_key.pem
```
## アプリケーション作成
※< >はいれなくていいです。

```
fn create app --annotation oracle.com/oci/subnetIds='["<Oracle Functions用に作成したサブネットOCID>"]' --config TENANT_OCID=<テナントOCID> --config USER_OCID=<Oracle Functions用ユーザOCID> --config FINGERPRINT=<Oracle Functions用ユーザ 鍵のフィンガープリント> --config PASSPHRASE=<OCI秘密鍵のパスフレーズ> --config REGION=<リージョン 今回はus-phoenix-1> --config PRIVATE_KEY_NAME=<OCI秘密鍵 今回はoci_api_key.pem> --config NAMESPACE=<ネームスペース 本手順で使用したやつ> --config BUCKET_NAME=<対象のバケット名 今回はaraki-bucket> text2pdf 
```

## デプロイ
```
fn -v deploy --app text2pdf --build-arg PRIVATE_KEY_NAME=<OCI秘密鍵名>
※今回は以下。
fn -v deploy --app text2pdf --build-arg PRIVATE_KEY_NAME=oci_api_key.pem

デプロイに成功したら消しておく
rm oci_api_key.pem
```

## PDFに変換
```
echo -n 'test.txt' | fn invoke text2pdf convert
※以下表示される。
PDF test.pdf written to storage bucket - araki-bucket
```

## 確認
```
echo -n 'araki-bucket' | fn invoke fn-object-store-app listobjects
※以下表示される。
["test.pdf","test.txt","test2.txt"]
```

## 参考
https://github.com/abhirockzz/oracle-functions-oci-object-store
https://github.com/abhirockzz/fn-text2pdf

## 関連記事
[・Oracle Functionsに関するメモ](https://qiita.com/y-araki-qiita/items/f73f815ea60a93978cac)
[・Oracle Functionsセットアップ](https://qiita.com/y-araki-qiita/items/d1ed0551d8943adc3bb5)
[・Oracle FunctionsでAPEXのRestful Serviceと連携](https://qiita.com/y-araki-qiita/items/03e67f5bca570c526a7c)
[・Oracle FunctionsでTensorFlowによる画像分類](Oracle FunctionsでObject Storage操作)
[・Oracle FunctionsでEmail Deliveryと連携しメール送信](https://qiita.com/y-araki-qiita/items/5a580bb739b37198300d)
[・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)