【Oracle Cloud Infrastructure】Object Storage Service の概要とその主要な CLI コマンドについて

Oracle Cloud Infrastructure(OCI) のオブジェクト・ストレージの概要と簡単な使用例について書いていきます。


**本記事で取り扱うこと**

- OCI のオブジェクトストレージの概要・特徴・利用方法について
  - Amazon S3 互換 API について
- OCI CLI を使用した、オブジェクト・ストレージの利用方法
  - バケットの作成・取得
  - バケットへのオブジェクトのアップロード・ダウンロード・削除

前半では、OCI のオブジェクト・ストレージについて概観を眺めます。
後半では実際に OCI CLI （oci コマンド）を用いてオブジェクト・ストレージを操作します。各種コマンドの主要な引数についても併せて紹介し、実行例とともに示します。

なお、コマンドの引数や実行結果などは、記事をコンパクトに保つため details タグを使った折りたたみ形式で記載しています。 必要に応じて展開して参照ください。

**本記事で使用したOCI CLIのバージョン**

```shell-session
> oci -v
2.17.0
```

# オブジェクト・ストレージの概要

## オブジェクト・ストレージとは
reference: https://docs.oracle.com/ja-jp/iaas/Content/Object/Concepts/objectstorageoverview.htm

Oracle Cloud Infrastructure Object Storage は、その名の通り OCI の提供するオブジェクト・ストレージサービス。

OCI のオブジェクト・ストレージには3種のストレージクラス(Tier)がある。

- スタンダード  
頻繁にアクセスするオブジェクトを格納するストレージ。Amazon S3 に対応する。  
料金設定は 3.06 円/月・GB(2021年2月現在)。
- 低頻度アクセス   
2021年2月にリリースされた新しいストレージクラス。Amazon S3 IA に対応する。  
アーカイブと異なり、保管しているオブジェクトを即座に取り出すことができる。
- アーカイブ  
アクセス頻度が低く、長期間保存するオブジェクトを格納する低価格ストレージ。Amazon S3 Glacier に対応する。  
料金設定は 0.312 円/月・GB(2021年2月現在)。

## オブジェクト・ストレージの特徴

- **強い一貫性**  
OCI のオブジェクト・ストレージは強い一貫性をサポートしている。  
S3 でも先日サポートされた強い一貫性が、OCI でも同様にサポートされている。
- **暗号化**  
OCI のオブジェクト・ストレージでは、格納されるオブジェクトは常に暗号化される。  
これはデフォルトで有効になっており、無効にすることはできない。  
また、デフォルトでは暗号化キーは OCI によって自動生成されるものを利用するが、キーのローテーションや自前のキーを利用することも可能。
- **耐久性**  
オブジェクト・ストレージサービスは、99.95%のSLOを[設定している](https://docs.oracle.com/en-us/iaas/Content/General/Reference/servicelevelobjectives.htm)。  
耐久性としては、年間99.999999999%(11 nines)を掲げている[^1]。   
- **RMAN(Recovery Manager) との親和性**  
Oracle のマネージドサービスであることのメリット。  
RMAN を使用して、データベースのバックアップを透過的に直接オブジェクト・ストレージに格納することができる。  
- **名前空間によるバケット名の分離(後述)**

[^1]: https://www.oracle.com/cloud/storage/object-storage-faq.html の `How durable is data stored in Oracle Cloud Infrastructure Object Storage?` に記載がある。

### オブジェクト・ストレージ・ネームスペース
reference: https://docs.oracle.com/ja-jp/iaas/Content/Object/Tasks/understandingnamespaces.htm

OCI のオブジェクト・ストレージでは、各テナンシごとにグローバルに一意な名前空間が切られ、その中にバケットが作成される。
この機構によって、Amazon S3 バケットの命名で発生するような他ユーザとの名前衝突を回避している。
なお、ネームスペースはアカウント作成時に自動的に生成される値である。

名前空間はテナンシごとのグローバルな値だが、バケット名は同一テナント・同一リージョン内で一意であればよい。つまり、同一テナント・別リージョンには同名のバケットを作成できる。

ネームスペースをOCI CLIから確認するには、`oci os ns get` を実行する[^2]。

```shell-session
> oci os ns get
{
  "data": "xxxxxxxxxxx"
}
```

[^2]: 以降、本記事では `allow group Group_Name to manage object-family in compartment Compartment_Name` ポリシが適用されているユーザを利用してAPIを利用する。

## オブジェクト・ストレージの利用方法

以下の利用方法がある。

- **OCIコンソール**  
Webブラウザからオブジェクト・ストレージを操作する。
- **OCI CLI**  
コマンドライン・インターフェースからオブジェクト・ストレージを操作する。  
本記事ではこちらの利用方法について、基礎的な部分を確認していく。
- **REST API**  
以下のAPIが利用できる。
  - Object Storage Service API（OCIの提供する通常のWebAPI）
  - Amazon S3互換API（後述）
  - Swift API（RMANで利用される）
- **SDK**  
以下の言語向けにSDKが[提供されている](https://docs.oracle.com/ja-jp/iaas/Content/API/Concepts/sdks.htm)。
  - Java
  - Python
  - TypeScript/JavaScript
  - .NET
  - Go
  - Ruby
- **Storage Gateway**  
[Storage Gateway](https://www.oracle.com/jp/cloud/storage/storage-gateway.html)を使うことで、オブジェクト・ストレージをオンプレサーバやコンピュートインスタンスにNFSとしてマウントすることもできる。

## Amazon S3 互換 API
ref: https://docs.oracle.com/ja-jp/iaas/Content/Object/Tasks/s3compatibleapi.htm

OCI オブジェクト・ストレージの REST API では、Amazon S3 互換の API も提供されている。
これにより、AWS SDK から、API エンドポイントを変更するだけで OCI オブジェクト・ストレージを操作できる。

サポートされている API や、SDK での利用例も上記参考 URL に記載されているので、興味があれば参照してみるといいだろう。

# 各種OCI CLIコマンド

ここからは実際にCLIを使ってリソースを操作しながら各種概念を確認していく。

## バケット操作

### `oci os bucket create`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/bucket/create.html

OCI CLIを用いたバケットの作成では、`oci os bucket create`コマンドを用いる。
コマンドの主要な引数は以下の通り。

<details><summary>`oci os bucket create` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --name [text] | **Required** | バケット名 |
| --compartment-id, -c [text] | **Required** | バケットを作成するコンパートメントOCID |
| --storage-tier [text] | _Optional_<br>(デフォルト: `Standard`) | ストレージクラス。`Standard`または`Archive`を指定する。|
| --object-events-enabled [boolean] | _Optional_<br>(デフォルト: `false`) | 有効にすると、オブジェクトの作成・削除・更新イベントを Oracle Cloud Infrastructure Events で利用できる。<br>Events は Functions(Lambdaみたいなもの)のトリガとしての用途などがある。  |
| --versioning [text] | _Optional_<br>(デフォルト: `Disabled`) | バージョニングを利用するか否か。`Disabled`または`Enabled`を指定する。<br>有効になると、オブジェクトの上書きや削除時に自動的にバージョニングが行われる。 |
| --public-access-type [text] | _Optional_<br>(デフォルト: `NoPublicAccess`) | パブリックアクセスの制御に関するパラメータ。`NoPublicAccess`, `ObjectRead`, または`ObjectReadWithoutList`を指定する。 |
| --kms-key-id [text] | _Optional_ | Vault に作成した暗号化キーのOCIDを設定し、これをオブジェクトの暗号化キーとして利用する。 |
| --metadata [complex type] | _Optional_ | カスタムメタデータを設定する。<br>引数にはJSON形式の文字列またはファイルを`file://path/to/file`形式で指定できる。 |
| --defined-tags [complex type] | _Optional_ | [定義済みタグ](https://docs.oracle.com/ja-jp/iaas/Content/Tagging/Tasks/managingtagsandtagnamespaces.htm#Managing_Tags_and_Tag_Namespaces)を設定する。<br>引数にはJSON形式の文字列またはファイルを`file://path/to/file`形式で指定できる。 |
| --freeform-tags [complex type] | _Optional_ | [フリーフォーム・タグ](https://docs.oracle.com/ja-jp/iaas/Content/Tagging/Concepts/understandingfreeformtags.htm#Understanding_Freeform_Tags)を設定する。<br>引数にはJSON形式の文字列またはファイルを`file://path/to/file`形式で指定できる。 |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

**コマンド実行例**

OCI CLI を用いてバケットを作成する例を以下に示す。

<details><summary>CLI によるバケット作成例①: 必須パラメータのみ</summary><div>

```shell-session
> oci os bucket create --name qiita-test --compartment-id ocid1.compartment.exampleuniqueID
{
  "data": {
    "approximate-count": null,
    "approximate-size": null,
    "compartment-id": "ocid1.compartment.exampleuniqueID",
    "created-by": "ocid1.user.oc1.exampleuniqueID",
    "defined-tags": {},
    "etag": "hogehoge",
    "freeform-tags": {},
    "id": "ocid1.bucket.oc1.ap-tokyo-1.exampleuniqueID",
    "is-read-only": false,
    "kms-key-id": null,
    "metadata": {},
    "name": "qiita-test",
    "namespace": "fugafuga",
    "object-events-enabled": false,
    "object-lifecycle-policy-etag": null,
    "public-access-type": "NoPublicAccess",
    "replication-enabled": false,
    "storage-tier": "Standard",
    "time-created": "2021-01-06T09:13:13.194000+00:00",
    "versioning": "Disabled"
  },
  "etag": "hogehoge"
}
```
</div></details>

<details><summary>CLI によるバケット作成例②: JSON ファイルによるメタデータ付与</summary><div>

```shell-session
> cat metadata.json                                                                     2196ms
{
    "label": "qiita",
    "type": "Standard",
    "metadata-type": "json-file"
}
> oci os bucket create --compartment-id ocid1.compartment.oc1..exampleuniqueID--name qiita-test-metadata-json --metadata file://path/to/metadata.json
{
  "data": {
    "approximate-count": null,
    "approximate-size": null,
    "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
    "created-by": "ocid1.user.oc1..exampleuniqueID",
    "defined-tags": {},
    "etag": "72c119a1-26e1-431c-8b7c-75e8eded81bc",
    "freeform-tags": {},
    "id": "ocid1.bucket.oc1.ap-tokyo-1.exampleuniqueID",
    "is-read-only": false,
    "kms-key-id": null,
    "metadata": {
      "label": "qiita",
      "metadata-type": "json-file",
      "type": "Standard"
    },
    "name": "qiita-test-metadata-json",
    "namespace": "hogehoge",
    "object-events-enabled": false,
    "object-lifecycle-policy-etag": null,
    "public-access-type": "NoPublicAccess",
    "replication-enabled": false,
    "storage-tier": "Standard",
    "time-created": "2021-01-07T10:27:29.034000+00:00",
    "versioning": "Disabled"
  },
  "etag": "72c119a1-26e1-431c-8b7c-75e8eded81bc"
}
```
</div></details>

<details><summary>CLI によるバケット作成例③: Vault に作成したキーを使用する</summary><div>

Vault に作成したキーをオブジェクト・ストレージから利用する場合は、`Allow service objectstorage-<region_name> to use keys in compartment <compartment_name>` ポリシの適用が必要。

```shell-session
> oci os bucket create --compartment-id ocid1.compartment.oc1..exampleuniqueID--kms-key-id ocid1.key.oc1.ap-tokyo-1.exampleuniqueID --name qiita-test-vault-key
{
  "data": {
    "approximate-count": null,
    "approximate-size": null,
    "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
    "created-by": "ocid1.user.oc1..exampleuniqueID",
    "defined-tags": {},
    "etag": "1a1d5444-58d1-4266-9651-857616c17988",
    "freeform-tags": {},
    "id": "ocid1.bucket.oc1.ap-tokyo-1.exampleuniqueID",
    "is-read-only": false,
    "kms-key-id": "ocid1.key.oc1.ap-tokyo-1.exampleuniqueID",
    "metadata": {},
    "name": "qiita-test-vault-key",
    "namespace": "hogehoge",
    "object-events-enabled": false,
    "object-lifecycle-policy-etag": null,
    "public-access-type": "NoPublicAccess",
    "replication-enabled": false,
    "storage-tier": "Standard",
    "time-created": "2021-01-08T01:09:50.131000+00:00",
    "versioning": "Disabled"
  },
  "etag": "1a1d5444-58d1-4266-9651-857616c17988"
}
```
</div></details>

<details><summary>CLI によるバケット作成例④: `--from-json` でパラメータを指定する</summary><div>

```shell-session
> cat bucket_create_parameters.json
{
  "compartmentId": "ocid1.compartment.oc1..exampleuniqueID",
  "freeformTags": {
    "type": "jsonparams"
  },
  "name": "qiita-json-bucket",
  "objectEventsEnabled": false,
  "publicAccessType": "NoPublicAccess",
  "storageTier": "Standard",
  "versioning": "Disabled"
}
> oci os bucket create --from-json file://path/to/bucket_create_parameters.json
{
  "data": {
    "approximate-count": null,
    "approximate-size": null,
    "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
    "created-by": "ocid1.user.oc1..exampleuniqueID",
    "defined-tags": {},
    "etag": "c415f313-61e9-4c14-933e-df8ddb33f75d",
    "freeform-tags": {
      "type": "jsonparams"
    },
    "id": "ocid1.bucket.oc1.ap-tokyo-1.exampleuniqueID",
    "is-read-only": false,
    "kms-key-id": null,
    "metadata": {},
    "name": "qiita-json-bucket",
    "namespace": "hogehoge",
    "object-events-enabled": false,
    "object-lifecycle-policy-etag": null,
    "public-access-type": "NoPublicAccess",
    "replication-enabled": false,
    "storage-tier": "Standard",
    "time-created": "2021-01-07T10:00:35.751000+00:00",
    "versioning": "Disabled"
  },
  "etag": "c415f313-61e9-4c14-933e-df8ddb33f75d"
}
```
</div></details>

### `oci os bucket list`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/bucket/list.html

バケット情報一覧の取得では、`oci os bucket list`コマンドを用いる。
コマンドの主要な引数は以下の通り。

<details><summary>`oci os bucket list` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --compartment-id, -c [text] | **Required** | コンパートメントのOCID |
| --all | _Optional_ | 全てのバケットを取得する。この引数が付与されている場合は `--limit` は利用できない。 |
| --fields [text] | _Optional_ | アウトプットに含めるフィールドを指定する。現在は`tags`のみサポートしている。 |
| --limit [integer] | _Optional_ | 表示するバケットの数 |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

**コマンド実行例**

OCI CLI を用いてバケットリストを取得する例を以下に示す。

<details><summary>CLI によるバケットリスト取得例①: 必須パラメータのみ</summary><div>

```shell-session
> oci os bucket list --compartment-id ocid1.compartment.oc1..exampleuniqueID
{
  "data": [
    {
      "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
      "created-by": "ocid1.user.oc1..exampleuniqueID",
      "defined-tags": null,
      "etag": "e5dc2492-3694-48a0-b79a-d260cc129404",
      "freeform-tags": null,
      "name": "qiita-test",
      "namespace": "hogehoge",
      "time-created": "2021-01-07T01:08:23.044000+00:00"
    },
    {
      "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
      "created-by": "ocid1.user.oc1..exampleuniqueID",
      "defined-tags": null,
      "etag": "4a2346f4-f982-4558-8814-77ff1c88d643",
      "freeform-tags": null,
      "name": "qiita-test-freeformtag",
      "namespace": "hogehoge",
      "time-created": "2021-01-07T09:41:36.934000+00:00"
    },
    {
      "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
      "created-by": "ocid1.user.oc1..exampleuniqueID",
      "defined-tags": null,
      "etag": "d082fdc7-e077-46e1-8b52-a730d0bb2fd1",
      "freeform-tags": null,
      "name": "qiita-test-jsonfile",
      "namespace": "hogehoge",
      "time-created": "2021-01-07T01:12:42.436000+00:00"
    }
  ]
}
```
</div></details>

<details><summary>CLI によるバケットリスト取得例②: `--field tags` を指定</summary><div>

①では`null`となっていた`freeform-tags`に正しく値が表示されていることが確認できる。

```shell-session
> oci os bucket list --fields tags --compartment-id ocid1.compartment.oc1..exampleuniqueID
{
  "data": [
    {
      "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
      "created-by": "ocid1.user.oc1..exampleuniqueID",
      "defined-tags": {},
      "etag": "e5dc2492-3694-48a0-b79a-d260cc129404",
      "freeform-tags": {},
      "name": "qiita-test",
      "namespace": "hogehoge",
      "time-created": "2021-01-07T01:08:23.044000+00:00"
    },
    {
      "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
      "created-by": "ocid1.user.oc1..exampleuniqueID",
      "defined-tags": {},
      "etag": "4a2346f4-f982-4558-8814-77ff1c88d643",
      "freeform-tags": {
        "label": "qiita",
        "metadata-type": "json-file",
        "type": "Standard"
      },
      "name": "qiita-test-freeformtag",
      "namespace": "hogehoge",
      "time-created": "2021-01-07T09:41:36.934000+00:00"
    },
    {
      "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
      "created-by": "ocid1.user.oc1..exampleuniqueID",
      "defined-tags": {},
      "etag": "d082fdc7-e077-46e1-8b52-a730d0bb2fd1",
      "freeform-tags": {},
      "name": "qiita-test-jsonfile",
      "namespace": "hogehoge",
      "time-created": "2021-01-07T01:12:42.436000+00:00"
    }
  ]
}
```
</div></details>


### `oci os bucket get`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/bucket/get.html

特定のバケット情報の取得では、`oci os bucket get`コマンドを用いる。
コマンドの主要な引数は以下の通り。

<details><summary>`oci os bucket get` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --bucket-name, --name, -bn [text] | **Required** | バケット名 |
| --fields [text] | _Optional_ | アウトプットに含めるフィールドを指定する。<br>`approximateCount`, `approximateSize` をサポートしている。 |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

**コマンド実行例**

<details><summary>CLI によるバケット取得例①: 必須パラメータのみ</summary><div>

```shell-session
> oci os bucket get --name qiita-test
{
  "data": {
    "approximate-count": null,
    "approximate-size": null,
    "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
    "created-by": "ocid1.user.oc1..exampleuniqueID",
    "defined-tags": {},
    "etag": "e5dc2492-3694-48a0-b79a-d260cc129404",
    "freeform-tags": {},
    "id": "ocid1.bucket.oc1.ap-tokyo-1.exampleuniqueID",
    "is-read-only": false,
    "kms-key-id": null,
    "metadata": {
      "label": "qiita",
      "type": "Standard"
    },
    "name": "qiita-test",
    "namespace": "hogehoge",
    "object-events-enabled": false,
    "object-lifecycle-policy-etag": null,
    "public-access-type": "NoPublicAccess",
    "replication-enabled": false,
    "storage-tier": "Standard",
    "time-created": "2021-01-07T01:08:23.044000+00:00",
    "versioning": "Disabled"
  },
  "etag": "e5dc2492-3694-48a0-b79a-d260cc129404"
}
```
</div></details>

<details><summary>CLI によるバケット取得例②: `--fields approximateSize` を指定</summary><div>

バケット取得例①では `null` だった `.data.approximate-size` の値が `0` と表示されていることが確認できる。
この時点でバケットにオブジェクトは存在しないため、`0` が表示されている。 

```shell-session
> oci os bucket get --name qiita-test --fields approximateSize
{
  "data": {
    "approximate-count": null,
    "approximate-size": 0,
    "compartment-id": "ocid1.compartment.oc1..exampleuniqueID",
    "created-by": "ocid1.user.oc1..exampleuniqueID",
    "defined-tags": {},
    "etag": "e5dc2492-3694-48a0-b79a-d260cc129404",
    "freeform-tags": {},
    "id": "ocid1.bucket.oc1.ap-tokyo-1.exampleuniqueID",
    "is-read-only": false,
    "kms-key-id": null,
    "metadata": {
      "label": "qiita",
      "type": "Standard"
    },
    "name": "qiita-test",
    "namespace": "hogehoge",
    "object-events-enabled": false,
    "object-lifecycle-policy-etag": null,
    "public-access-type": "NoPublicAccess",
    "replication-enabled": false,
    "storage-tier": "Standard",
    "time-created": "2021-01-07T01:08:23.044000+00:00",
    "versioning": "Disabled"
  },
  "etag": "e5dc2492-3694-48a0-b79a-d260cc129404"
}
```
</div></details>

### `oci os bucket delete`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/bucket/delete.html

バケットの削除では、`oci os bucket delete` コマンドを用いる。
コマンドの主要な引数は以下の通り。

<details><summary>`oci os bucket delete` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --bucket-name, --name, -bn [text] | **Required** | バケット名 |
| --force | _Optional_ | 確認を表示せず即座に削除を実行するためのオプション |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

**コマンド実行例**

<details><summary>CLI によるバケット削除例①: 必須パラメータのみ</summary><div>

```shell-session
> oci os bucket delete --name qiita-test-for-deletion
Are you sure you want to delete this resource? [y/N]: y
> oci os bucket delete --name qiita-test
Are you sure you want to delete this resource? [y/N]: n
Abort:
>
```
</div></details>

## オブジェクト操作

前章まででバケットの操作を確認した。
ここからは実際に作成したバケットに対してオブジェクトをアップロードし、動作を確認していこう。

本節では、特に断りがない場合以下のコマンドで作成されたバケットを使用する。

```shell-session
> oci os bucket create \
  --name qiita-test \
  --compartment-id ocid1.compartment.oc1..exampleuniqueID
```

### `oci os object put`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/object/put.html

バケットへオブジェクトをアップロードするには、`oci os object put` コマンドを用いる。
ディレクトリを対象とした一括アップロードには `oci os object bulk-upload` コマンドを用いる（本記事では扱わない）。

コマンドの主要な引数は以下の通り。

<details><summary>`oci os object put` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --bucket-name, --name, -bn [text] | **Required** | バケット名 |
| --file [filename] | **Required** | アップロードするファイルを指定する。`-` を指定すると標準入力から受け取ることができる。 |
| --name [text] | _Optional_ | オブジェクト名 |
| --content-md5 [text] | _Optional_ | オブジェクトの put リクエストに Content-MD5 ヘッダを付与し、アップロードしたオブジェクトの完全性をチェックする |
| --disable-parallel-uploads | _Optional_ | マルチパート・アップロード時に並列アップロードを行わない |
| --force | _Optional_ | 同名のオブジェクトがすでにバケットに存在する場合に、確認をせずに上書きする |
| --no-multipart | _Optional_ | マルチパート・アップロードを行わない |
| --no-overwrite | _Optional_ | 同名のオブジェクトがすでにバケットに存在する場合に、上書きを行わない |
| --parallel-upload-count [integer range] | _Optional_<br>(デフォルト: 3) | 並列アップロードの最大数 |
| --part-size [integer] | _Optional_<br>(デフォルト: 128) | マルチパート・アップロードの際に分割するサイズを MiB 単位で指定する。 |
| --verify-checksum | _Optional_ | アップロード後に、ローカルのファイルとアップロードしたファイルの間で MD5 チェックサムによるチェックを行う |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

なお、オブジェクト名にスラッシュを含む接頭辞文字列を使用することで、ディレクトリ構造をシミュレートしてバケットに格納できる。

**コマンド実行例**

<details><summary>CLI によるオブジェクトアップロード例①: 必須パラメータのみ</summary><div>

```shell-session
> oci os object put \
             --bucket-name qiita-test \
             --file ./testfile.txt
Uploading object  [####################################]  100%
{
  "etag": "e5c937cd-b51f-4990-9f19-c5b1de10596d",
  "last-modified": "Fri, 08 Jan 2021 08:36:51 GMT",
  "opc-content-md5": "ZllWSF64s0R+jxuXwKohWw=="
}
```

</div></details>

<details><summary>CLI によるオブジェクトアップロード例②: `--verify-checksum` によるアップロード結果チェック</summary><div>

```shell-session
> openssl md5 -binary ./testfile.txt | base64
ZllWSF64s0R+jxuXwKohWw==
> oci os object put \
             --bucket-name qiita-test \
             --file ./testfile.txt \
             --name testfile-verified.txt \
             --verify-checksum
Uploading object  [####################################]  100%
{
  "etag": "58bc7eaf-0d53-4ab6-b72b-d2a28f3cf408",
  "last-modified": "Fri, 08 Jan 2021 08:38:48 GMT",
  "opc-content-md5": "ZllWSF64s0R+jxuXwKohWw=="
}
md5 checksum matches [Local: ZllWSF64s0R+jxuXwKohWw==]
```

</div></details>

<details><summary>CLI によるオブジェクトアップロード例③: `--content-md5` によるアップロード結果チェック（失敗例）</summary><div>

```shell-session
> openssl md5 -binary ./dummyfile.txt | base64
1B2M2Y8AsgTpgAmY7PhCfg==
> oci os object put \
             --bucket-name qiita-test \
             --file ./testfile.txt \
             --name testfile-failed.txt \
             --content-md5 1B2M2Y8AsgTpgAmY7PhCfg==
Uploading object  [####################################]  100%
ServiceError:
{
    "code": "UnmatchedContentMD5",
    "message": "The computed MD5 hash (ZllWSF64s0R+jxuXwKohWw==) does not match the expected MD5 hash (1B2M2Y8AsgTpgAmY7PhCfg==)",
    "opc-request-id": "nrt-1:f_mu44JTzpNsuAJ9zQeeaU0eBP7a4PUpr_CJp9Xn-VCwnI4CQsXpaG59hTkH_VoW",
    "status": 400
}
```
</div></details>

<details><summary>CLI によるオブジェクトアップロード例④: マルチパート・アップロード（大容量ファイルのアップロード）</summary><div>

`Split file into 8 parts for upload.` と表示されていることがわかる。

```shell-session
> ls -lh 1G.dummy
-rw-r--r-- 1 testuser testuser 1000M Jan  8 14:58 1G.dummy
> oci os object put \
             --bucket-name qiita-test \
             --file ./1G.dummy \
             --profile APITEST
Upload ID: 6fd34c7d-555d-c0d8-b8e2-28c28eb9fd57
Split file into 8 parts for upload.
Uploading object  [####################################]  100%
{
  "etag": "305b9e53-453a-4d1c-a3af-7c8f238115ce",
  "last-modified": "Fri, 08 Jan 2021 08:43:27 GMT",
  "opc-multipart-md5": "XL33HVbpOwkyd+JY0YSxPg==-8"
}
```
</div></details>

### `oci os object list`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/object/list.html

バケットに格納されているオブジェクトのリストを取得するには、`oci os object list` コマンドを用いる。
コマンドの主要な引数は以下の通り。

<details><summary>`oci os object list` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --bucket-name, -bn [text] | **Required** | バケット名 |
| --all | _Optional_ | 全結果を取得する。`--limit` との併用はできない。 |
| --delimiter [text] | _Optional_ | 指定されたデリミタを含むオブジェクトを表示しないよう指定する。`--prefix` と併用して、特定の階層直下に存在するオブジェクトのみを表示できる。 |
| --start [text] | _Optional_ | オブジェクトを取得する始点を指定する。 |
| --end [text] | _Optional_ | オブジェクトを取得する終点を指定する。辞書順で指定されたパラメータ以前のオブジェクトを取得する。 |
| --fields [text] | _Optional_<br>(デフォルト: `name,size,timeCreated,md5` ) | 結果に含まれるフィールドを指定する。指定しなかったフィールドの値は `null` となる。 |
| --limit [integer] | _Optional_<br>(デフォルト: `100`) | 表示するオブジェクトの最大数を指定する。 |
| --page-size [integer] | _Optional_ | ページ分割におけるページサイズを指定する。 |
| --prefix [text] | _Optional_ | 指定されたプレフィクスを持つオブジェクトを取得する。 |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

以下の例では、図に示すようにオブジェクトを配置したバケットに対してコマンドを実行した結果を示す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66988/72664e19-057a-bb07-ffe5-6a2bf2757191.png)


<details><summary>CLI によるオブジェクトリスト取得例①: 必須パラメータのみ </summary><div>

```shell-session
> oci os object list -bn qiita-test
{
  "data": [
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent1/child1/fileA.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:54.011000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent1/child1/fileB.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:54.064000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent1/child2/fileC.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:54.067000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent1/child2/fileD.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:53.968000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent1/parentFile.txt",
      "size": 0,
      "time-created": "2021-02-02T10:59:31.704000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child1/fileA.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:53.977000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child1/fileB.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:54.033000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child2/fileC.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:53.986000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child2/fileD.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:53.924000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/parentFile.txt",
      "size": 0,
      "time-created": "2021-02-02T10:59:38.756000+00:00",
      "time-modified": null
    }
  ],
  "prefixes": []
}
```
</div></details>

<details><summary>CLI によるオブジェクトリスト取得例②: `--limit` の指定 </summary><div>

```shell-session
> oci os object list -bn qiita-test --limit 2
{
  "data": [
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent1/child1/fileA.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:54.011000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent1/child1/fileB.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:54.064000+00:00",
      "time-modified": null
    }
  ],
  "next-start-with": "parent1/child2/fileC.txt",
  "prefixes": []
}
```
</div></details>

<details><summary>CLI によるオブジェクトリスト取得例③: `--prefix` の指定 </summary><div>

`parent2/` をプレフィクスにもつ（`parent2/` フォルダ以下の）オブジェクトが全て取得されていることが確認できる。

```shell-session
> oci os object list -bn qiita-test --prefix parent2/
{
  "data": [
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child1/fileA.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:53.977000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child1/fileB.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:54.033000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child2/fileC.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:53.986000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/child2/fileD.txt",
      "size": 0,
      "time-created": "2021-02-02T09:35:53.924000+00:00",
      "time-modified": null
    },
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/parentFile.txt",
      "size": 0,
      "time-created": "2021-02-02T10:59:38.756000+00:00",
      "time-modified": null
    }
  ],
  "prefixes": []
}
```
</div></details>

<details><summary>CLI によるオブジェクトリスト取得例④: `--delimiter` と `--prefix` の併用 </summary><div>

`parent2/` 直下のファイルのみが表示されていることが確認できる。

```shell-session
> oci os object list -bn qiita-test --prefix parent2/ --delimiter /
{
  "data": [
    {
      "etag": null,
      "md5": "1B2M2Y8AsgTpgAmY7PhCfg==",
      "name": "parent2/parentFile.txt",
      "size": 0,
      "time-created": "2021-02-02T10:59:38.756000+00:00",
      "time-modified": null
    }
  ],
  "prefixes": [
    "parent2/child1/",
    "parent2/child2/"
  ]
}
```
</div></details>

### `oci os object get`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/object/get.html

バケットからオブジェクトをダウンロードするには、`oci os object get` コマンドを用いる。
ディレクトリを対象とした一括ダウンロードには `oci os object bulk-download` コマンドを用いる（本記事では扱わない）。
コマンドの主要な引数は以下の通り。

<details><summary>`oci os object get` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --bucket-name, --name, -bn [text] | **Required** | バケット名 |
| --file [filename] | **Required** | ダウンロード後のファイル名を指定する。`-` を指定すると標準入力から受け取ることができる。 |
| --name [text] | **Required** | ダウンロードするオブジェクト名 |
| --multipart-download-threshold [integer range] | _Optional_ | 対象のオブジェクトのサイズがここで指定したサイズ(MiB)以上だった場合、マルチパート・ダウンロードを行う。最小値は 128 MiB。 |
| --parallel-download-count [integer] | _Optional_<br>(デフォルト: 10) | マルチパート・ダウンロードを行う際の並列数 |
| --part-size [integer] | _Optional_<br>(デフォルト: 128) | マルチパート・ダウンロードを行う際の各パートのサイズ。最小値は 128 MiB。 |
| --version-id [text] | _Optional_ | ダウンロードするオブジェクトのバージョンを指定する |
| --namespace-name, --namespace, -ns [text] | _Optional_ | バケットを取得する名前空間を指定する。<br>デフォルトでは`oci os ns get`で返ってくる値が入っている。 |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

**コマンド実行例**

<details><summary>CLI によるオブジェクトダウンロード例①: 必須パラメータのみ</summary><div>

```shell-session
> oci os object get \
  --file testfile.txt \
  --name testfile.txt
Downloading object  [####################################]  100%
> ls
testfile.txt
```
</div></details>

### `oci os object delete`
ref: https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/cmdref/os/object/delete.html

バケットからオブジェクトを削除するには、`oci os object delete` コマンドを用いる。
ディレクトリを対象とした一括削除には `oci os object bulk-delete` コマンドを用いる（本記事では扱わない）。
コマンドの主要な引数は以下の通り。

<details><summary>`oci os object delete` コマンドの主要な引数</summary><div>

| 引数 | Required/Optional | 説明 |
|:-:|:-:|:-:|
| --bucket-name, -bn [text] | **Required** | バケット名 |
| --object-name, --name [text] | **Required** | オブジェクト名 |
| --force | _Optional_ | 確認を表示せず即座に削除を実行するためのオプション |
| --version-id [text] | _Optional_ | バージョニングが有効化されているバケットの際に、削除するオブジェクトのバージョンを指定する。 |
| --from-json [text] | _Optional_ | 各種パラメータを JSON ファイルから指定することができる。<br>JSON の形式は、[--generate-full-command-json-input オプション](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.17.0/oci_cli_docs/oci.html#cmdoption-generate-full-command-json-input)で生成されるものを参考にする。 |

</div></details>

**コマンド実行例**

<details><summary>CLI によるオブジェクト削除例①: 必須パラメータのみ</summary><div>

```shell-session
> oci os object list --bucket-name qiita-test
{
  "data": [
    {
      "etag": null,
      "md5": "ZllWSF64s0R+jxuXwKohWw==",
      "name": "testfile.txt",
      "size": 24,
      "time-created": "2021-01-12T01:07:02.061000+00:00",
      "time-modified": null
    }
  ],
  "prefixes": []
}
> oci os object delete \
  --bucket-name qiita-test \
  --object-name testfile.txt
Are you sure you want to delete this resource? [y/N]: y
> oci os object list --bucket-name qiita-test
{
  "prefixes": []
}
```
</div></details>

# おわりに

Oracle Cloud Infrastructure の Object Storage Service について、さわりの部分を説明してきました。
本記事では説明しませんでしたが、 ライフサイクルポリシーを設定することでオブジェクト・ストレージからアーカイブ・ストレージへの移動を自動化したり、レプリケーションポリシーを設定することで別のリージョンのバケットにオブジェクトをレプリケーションすることもでき、基本的なオブジェクトストレージの機能は備えているようです。

## see also

- [公式ドキュメント](https://docs.oracle.com/ja-jp/iaas/Content/Object/Concepts/objectstorageoverview.htm)
- [オブジェクト・ストレージ概要(Speaker Deck)](https://speakerdeck.com/ocise/ociji-shu-zi-liao-obuziekutosutorezi-gai-yao)