皆さんこんにちは。最近引っ越しをしようか悩んでいるid:k-furusawa--gです。
今回はOracle Cloud Infrastructure(以下OCI)向けのツール開発を作成したので記事にしようかと思います。
目次です。
ツールを開発するきっかけ
弊社が担当したある案件で、ObjectStorageに大量のオブジェクトを配置するものがありました。この際、クライアントツールがあれば顧客にも提供しやすいという話題が出たのですが、S3向けにはいろいろあってもObjectStorageに接続可能なツールの調査に時間がかかり、公式でそういうの出してくれないかなぁって思ったのがきっかけです。
他にも以下のような問題に直面したためにツール開発は必要と考えました。
作りっぱなしで迷子になるストレージがある
これはストレージに関わらずインスタンスやネットワークなどのすべてのクラウドリソースに言えることなのですが、OCIはコンパートメント×リージョンでリソースを格納できるスペースが区切れるため、リソース管理が大変です。AWSでも、あるリージョンでテスト的に作成したリソースの管理がそのリージョンへの切り替えを滅多にしない状態になると忘れてしまいがちです。OCIはそこにコンパートメントが加わるので棚卸も大変ですね。
せめてコンパートメント選択のみで済ませたいと度々感じました。
公式のコンソールでは確認できなくなるオブジェクトに対処したい
ObjectStorageは以下のことをすると公式コンソールから確認も操作もできなくなるオブジェクトを作成できます。これに対処するためにも、ツール開発が必要でした。
ObjectStorageのcontent-dispositionヘッダは破損させることができる
実はAPIやCLIを利用してオブジェクトの content-disposition
ヘッダを破壊することができます。それも割と簡単に。
やり方は、PutObjectにて content-disposition
を指定する際に attachment
や filename
などの値を意図的に含めるだけです。すると、 content-disposition
ヘッダのパースに失敗でもしているのか、それともバリデーションチェックしていないのか、 content-disposition
ヘッダに同じ値が2つ入ってしまいクライアントで開こうとしたりすると ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
エラーが発生します。当然、コンソールでも発生します。
ちなみにGetObjectする分には何も起きないのでCLIやAPI利用者は間違ってヘッダを破損させても気づくことは滅多にないです。
既存のツールは存在しない?
問題にしている部分を解決できるようなツールは存在しないのでしょうか。例えばS3のクライアントツールはたくさんありますね。あれを利用できないでしょうか。
ObjectStorageとAWS S3の違い
その前に少しS3とのお話を。
OCIのObjectStorageはAWSのS3と同じで中身はKeyとValueによって構成されており、指定されたKeyに紐づいたvalueを操作します(超ざっくりとした説明ですが)。オブジェクトの格納場所がバケットと呼ぶあたりも同じですね。ストレージを利用した細かな機能の違いはあれど、構造に違いはほぼ無いとみていいでしょう。
AWSのS3互換APIが存在しているだけあって、AWSのS3と同じ使われ方をするのは想定済みのようです。
しかしS3とは決定的に違う部分があり、それはディレクトリ構造を受け付けない点です。
S3はたとえばKeyに directory/sub_directory/Object.txt
のように指定すれば、疑似的にディレクトリ構造にしてくれます。公式コンソールからしてそうなるようにできています。一方のObjectStorageは、同じKeyを登録してもディレクトリにはならず、 directory/sub_directory/Object.txt
という名前のオブジェクトになります。KeyとValueをダイレクトに扱っているという点ではAWSのS3よりもメタな状態に近いと言えるかもしれません。
ただObjectStorageはダウンロードすると directory_sub_directory_Object.txt
という名前になってしまったり、階層を想定して名前を付けると長い名称がズラリとリストに並んだりして、なかなかにイケてません。
それだけでなく、APIのprefixもディレクトリパスのような文言が入り込むことを考慮していないらしく、うまく絞り込みを行ってくれません。S3向けのAPIに慣れていると相当に苦労します。
【2020/09/10 Update!】OCIコンソールが階層表示に対応しました!
OCIの公式コンソールでオブジェクトの名称がパスになっている場合は、ちゃんと階層で表示されるようになりました! やったね。
ただしフォルダのダウンロードとかはできないので、まだ機能はそろっていない様子ですね。
内部的な動きとしては、フォルダを作成すると0バイトの疑似的なフォルダオブジェクトが作成され、階層に見せているという具合です。AWS S3と同じですね!
ただし注意として、APIでパス違反になるようなオブジェクト名(//とか)をつけてアップロードするとコンソールが操作不能のエラーを吐くようになるので、十分にご注意ください!
ObjectStorageに接続可能なツールはあるのか
以上のS3との違いのせいなのか、せっかくS3互換APIが完備されているにもかかわらず、ObjectStorageはS3用のツール類などで接続してもうまく表示されてくれません。
いろいろ試してみたのですが、多くが認証でうまくいかず。なぜなのか調べてみると、S3の暗号化の仕様が変更になり、追加されたAWS-SHA2のヘッダにOCIのS3互換APIが対応していないので認証で落とされているようでした。
このあたりを考慮した認証はAWSのSDKのほうで行われているので、dotnetやJavaで組まれていて更新が最近のツールなら利用できそうですね。結果、「WinSCP」、「cyberduck」、「CloudBerry Explorer」などがS3互換APIを利用してS3としてObjectStorageに接続可能でした。ただ「WinSCP」は挙動が安定しませんでした。今のところ一番安定して動くのは「CloudBerry Explorer」ですね。
S3互換APIで見られるのは指定リージョンのバケットのみ
しかしS3互換APIは指定されたエンドポイントに含まれるリージョンに作られたバケットしか見ることができません。しかもどのバケットがどのコンパートメントにあったものなのかわからなくなります。S3と合うようにしているので当然と言えばそうですが、それこそタグに含めるなりヘッダに入れるなりしてほしかったですね。
プロジェクトごとに細かくコンパートメントを切って管理している現場や、複数リージョンをまたいで管理している場合は接続をいちいち切り替えなければいけません。地味に辛いところです。
ObjectStorageに接続可能な純正ツールは無い
以上のことからわかるように、S3互換APIを利用することで接続を可能とするツールはありますが、純粋にOCI認証を使ってObjectStorageに接続して各コンパートメント内のオブジェクトを管理するツールは今のところ存在しません。
ないなら作る!ObjectStorage専用ツール!
ないなら作ってしまえですね。
欲しいツールは何かを考える
作る上で何ができてほしいのかを考えます。結果、以下のことは最低限出来ることを決めました。
- S3互換APIは使わない(OCI認証を利用する)
- 全コンパートメントをツリー表示できるようにする
- 全リージョンのバケットをリストで見られる
- バケット内のディレクトリ階層表示を実現する
- ダウンロード時に階層構造を維持しながらダウンロードする
- 公式のコンソールでは確認できなくなるオブジェクトに対応する
特に 4 と 6 は絶対です。そして5も魅力的ですね。
難関「バケット内ディレクトリ構造を表示」を実現する
実装するものの中で、難しいのはぶっちゃけ1つだけです。ディレクトリ構造を表示させる方法ですね。
実現するには何が必要か
実現するために必要なものは何かを考えた際、ローカルのディレクトリ構造を解析するには何がいるかを考えました。C#ではDirectoryInfoクラスが必要不可欠ですね。これを利用するとローカルのファイルのパスが取れます。このパスと同じように、ObjectStorageの中にあるKey類をとれればいいわけですね。
よく考えたらすでにそれを実現して公開してくれているサービスがありますね! そう、AWSです!
頼りになるAWSのSDK
AWSのS3とObjectStorageの基本的な構造は同じという話は前述しました。S3向けのツールでは実現できているのですから、同じものをObjectStorage向けに用意してあげればいいわけですね。
そしてS3専用のDirectoryInfoはコードが公開されています!
OCIの公式SDKの紹介記事で、IOクラスを実装してほしいと書きましたが、こういった部分でAWSと差があるためです。AWSはツール開発をはじめサードパーティが役立てそうなものをたくさん公開しています。OCIを利用したサードパーティ開発を盛り上げるためにも、こうしたものは必要不可欠に思います。
とはいっても無いものは無いので、実装は自分で行いました。個人で作ったOCISDK(更新停止中)のほうにコードも公開しています! 全く同じではありませんが、よかったらどうぞ。
※一部誤解を与えてしまっているようですので注釈です。上で公開しているのはOCIのObjectStorage向けDirectoryInfoクラスです。ツールのコードではございません。本記事のツールのコードは現在、パブリックに可能かどうか自社で相談しております。誤解を招いて申し訳ございません。
【2020/09/14 Update!】コードをまるごとパブリックにしました
社内で協議した結果、パブリックにしちゃおうということで公開しました! 公式がディレクトリ階層の表示に対応したのでいい機会だと思います!
いろいろあって私の個人リポジトリ扱いですが、以下のリンクから参照できます。READMEにも書きましたが、試験的な開発の側面が相当に強いものです。テストが不完全、コードが整理され切っていない、などなど問題点も多いのでご注意ください。
完成図
まだ粗削りですが出来上がったアプリケーションは以下のようになりました!
まずOCI接続設定を可能にするために設定画面。MySQLのWorkbenchのように接続テストもできるようにしました。
接続後はコンパートメントが親と子の関係を保ってツリー上に表示されます。
コンパートメントを選ぶとバケットが表示されます。この時、全リージョンのバケットを拾い上げます。そして、バケットを選ぶと中身がディレクトリ構造で表示されます。
ディレクトリを選んでダウンロードを選択すると、フォームが開いて階層を維持するかOCI準拠でダウンロードするか選べます。
ダウンロードすると、選択したディレクトリの中身をディレクトリ構造を維持したままダウンロードできます。ちなみにバケットを丸ごとダウンロードすることもできます。
以上で最低限作ると決めた部分は実現されましたね! ツールなのでさらに機能を追加しました。
プロパティ画面を開けるようにしたり
複数ファイルをアップロードできるようにしたり
バケットやディレクトリを作成できるようにしたり
一般的なツールにあるだろう機能は一通り揃えました。本格的な作業を行う際に利用するにはまだまだ機能不足ではありますが、コンソールを使わずにObjectStorageを確認するには十分です。
おしまいに
いかがだったでしょうか。OCIはサードパーティ開発に関してはまだまだです(大きな企業との連携は進んでますが)。
公式のSDKもようやく登場して、開発環境が整うのはまだこれからといった具合ですが、AWSと共通している部分はありますので今回のようにオープンソースの活用など、工夫次第で開発ははかどるので積極的に探してみるといいでしょう。
また何かの開発記事が書ければなと思います。