【Oracle Cloud】JavaScript SDKを使ってOCIのObject Storageを操作してみた

##はじめに
Oracle Cloud Infrastructure(以下OCI)ではJavascript/TypescriptのSDK（以下JavaScript SDK）が提供されています。
今回は、JavaScript SDKを使って、OCIのObject Storageに対して操作を行う手順を紹介します。

##JavaScript SDKのインストール
OCI上のComputeインスタンス（OSはCentOS 7）にNode.jsをインストールします。
[Node.jsの公式サイト](https://nodejs.org/ja/download/package-manager/#debian-and-ubuntu-based-linux-distributions-enterprise-linux-fedora-and-snap-packages)で紹介されている、NodeSourceのリポジトリを追加して、yumでインストールをします。

https://github.com/nodesource/distributions/blob/master/README.md

```
$ curl -fsSL https://rpm.nodesource.com/setup_lts.x | sudo bash -
$ sudo yum install -y nodejs
```
次にSDKをインストールします。JavaScript SDKにはGithub、yumなどいくつかインストール方法がありますが、今回はnpmでインストールします。
https://www.npmjs.com/package/oci-sdk

`npm initで`アプリケーションディレクトリを作成し、`npm i oci-sdk`でインストールします。

```
$ mkdir app && cd app
$ npm init

$ npm i oci-sdk
```

##configファイルの設定
認証用のconfigファイルを作成していきます。
OCIのコンソール画面にログインし、メニューの「アイデンティティとセキュリティ」→「アイデンティティ」→「ユーザー」からユーザ詳細画面にアクセスし、「APIキー」→「APIキーの追加」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/82bc4615-1426-9acb-ee3e-df5f178b4ce1.png)

秘密キーをダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/5b3b74d4-9c5e-b4ff-52f6-4a28cfff6cb8.png)

構成ファイルのプレビューをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/7a043df4-a0ad-7b20-44e7-ba44868691c8.png)

Computeインスタンスに`~/.oci/config`ファイルを作成し、
先ほどコピーした内容を貼り付けます。

```bash:~/.oci/config
[DEFAULT]
user='userのOCID'
fingerprint='fingerprint'
tenancy='tenacyのOCID'
region=ap-tokyo-1
key_file=<path to your private keyfile> # TODO
```
`~/.oci`ディレクトリにダウンロードした秘密鍵を置き、configファイルのkey_fileのパスを書き換えます。

```bash:~/.oci/config
[DEFAULT]
user='userのOCID'
fingerprint='fingerprint'
tenancy='tenacyのOCID'
region=ap-tokyo-1
key_file=秘密鍵の絶対パス
```
##JavaScript SDKでObject Storageを操作
アプリケーションディレクトリのapp直下に、Object Storageにアップロードするファイルを作成します。

```bash
$ echo 'test' > test.txt
```
コードを書いていきます。
Githubに公開されているサンプルコードを参考にしています。
https://github.com/oracle/oci-typescript-sdk/blob/master/examples/javascript/objectstorage.js

```javascript:~/app/test.js
const common = require("oci-common");
const os = require("oci-objectstorage");
const fs = require("fs");

//認証オブジェクトを作成
const provider = new common.ConfigFileAuthenticationDetailsProvider();

const compartmentId = process.env.compartmentId; //コンパートメントID
const bucket = "test_sdk"; //Object StorageのBucket名
const fileLocation = "./test.txt" //Object Storageにアップロードするファイル
const object = "test.txt";  //アップロードされたファイルのオブジェクト名

//Object StorageのClientオブジェクトの作成
const client = new os.ObjectStorageClient({
    authenticationDetailsProvider: provider
});

(async () => {
    try {
        //namespaceの取得
        console.log("Getting the namespace...");
        const request = {};
        const response = await client.getNamespace(request);
        const namespace = response.value;

        console.log(namespace)

        //Bucketの作成
        console.log("Creating the source bucket.");
        const bucketDetails = {
            name: bucket,
            compartmentId: compartmentId
        };
        const createBucketRequest = {
            namespaceName: namespace,
            createBucketDetails: bucketDetails
        };
        const createBucketResponse = await client.createBucket(createBucketRequest);
        console.log("Create Bucket executed successfully" + JSON.stringify(createBucketResponse));

        //Bucket情報の取得
        console.log("Bucket is created. Fetch the bucket.");
        const getBucketRequest = {
            namespaceName: namespace,
            bucketName: bucket
        };
        const getBucketResponse = await client.getBucket(getBucketRequest);
        console.log("Get bucket executed successfully." + getBucketResponse.bucket);


        // streamの作成
        const stats = fs.statSync(fileLocation);
        const nodeFsBlob = new os.NodeFSBlob(fileLocation, stats.size);
        const objectData = await nodeFsBlob.getData();

        // ファイルアップロード
        console.log("Bucket is created. Now adding object to the Bucket.");
        const putObjectRequest = {
            namespaceName: namespace,
            bucketName: bucket,
            putObjectBody: objectData,
            objectName: object,
            contentLength: stats.size
        };
        const putObjectResponse = await client.putObject(putObjectRequest);
        console.log("Put Object executed successfully" + putObjectResponse);

        //アップロードされたファイルの取得
        console.log("Fetch the object created");
        const getObjectRequest = {
            objectName: object,
            bucketName: bucket,
            namespaceName: namespace
        };
        const getObjectResponse = await client.getObject(getObjectRequest);
        console.log("Get Object executed successfully.");

    } catch (error) {
        console.log("Error executing example " + error);
    }
})();


```
コンパートメントIDの環境変数をセットします。

```
$ export compartmentId=ocid1.xxxxxxxxxxxxxxxxxxxxx
```

コードを実行します。

```
$ node test.js
```

無事Object Storageにtest_sdkバケットが作成され、test.txtファイルがアップロードされていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/e2da64b8-e88a-781c-8cf9-3258a5d4e8f2.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226871/68cda002-19a0-bdd4-a65c-d761316fdbbc.png)

##補足：コードの解説
###モジュールのインポート

```javascript
const common = require("oci-common");
const os = require("oci-objectstorage");
const fs = require("fs");
```

###Object StorageのClientオブジェクトを定義
利用できるメソッドはドキュメントで確認できます。
https://docs.oracle.com/en-us/iaas/tools/typescript/1.19.5/classes/_objectstorage_lib_client_.objectstorageclient.html

```javascript
    const client = new os.ObjectStorageClient({
    authenticationDetailsProvider: provider
});
```

###namespaceの取得
Object Storageのnamespaceを取得します。

```javascript
        console.log("Getting the namespace...");
        const request = {};
        const response = await client.getNamespace(request);
        const namespace = response.value;

        console.log(namespace)
```

###Bucketの作成
Bucket名、Compartment名、namespaceを指定して作成します。

```javascript
        console.log("Creating the source bucket.");
        const bucketDetails = {
            name: bucket,
            compartmentId: compartmentId
        };
        const createBucketRequest = {
            namespaceName: namespace,
            createBucketDetails: bucketDetails
        };
        const createBucketResponse = await client.createBucket(createBucketRequest);
        console.log("Create Bucket executed successfully" + createBucketResponse);
```

###Bucket情報の取得
namespace、Bucket名を指定して取得します。

```javascript
        console.log("Bucket is created. Fetch the bucket.");
        const getBucketRequest = {
            namespaceName: namespace,
            bucketName: bucket
        };
        const getBucketResponse = await client.getBucket(getBucketRequest);
        console.log("Get bucket executed successfully." + getBucketResponse.bucket);

```

###ファイルアップロード

ファイルのsreamを作成し、namespace、バケット名、オブジェクト名を指定してファイルをアップロードします。

```javascript
        const stats = fs.statSync(fileLocation);
        const nodeFsBlob = new os.NodeFSBlob(fileLocation, stats.size);
        const objectData = await nodeFsBlob.getData();

        console.log("Bucket is created. Now adding object to the Bucket.");
        const putObjectRequest = {
            namespaceName: namespace,
            bucketName: bucket,
            putObjectBody: objectData,
            objectName: object,
            contentLength: stats.size
        };
        const putObjectResponse = await client.putObject(putObjectRequest);
        console.log("Put Object executed successfully" + putObjectResponse);
```

###アップロードしたオブジェクト情報の取得
Object名、Bucket名、namespaceを指定して取得します。

```javascript
        console.log("Fetch the object created");
        const getObjectRequest = {
            objectName: object,
            bucketName: bucket,
            namespaceName: namespace
        };
        const getObjectResponse = await client.getObject(getObjectRequest);
        console.log("Get Object executed successfully.");
```

##参考リンク
https://docs.oracle.com/ja-jp/iaas/Content/API/SDKDocs/typescriptsdk.htm
https://github.com/oracle/oci-typescript-sdk/blob/master/examples/javascript/objectstorage.js
https://docs.oracle.com/en-us/iaas/tools/typescript/1.19.5/modules/_objectstorage_lib_client_.html