読者です 読者をやめる 読者になる 読者になる

テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(akashic report) 進捗報告

akiradeveloper/akashic-storage · GitHub

今日は休日でしたので, 集中して開発することが出来ました.

現在実装して(簡単な)テスト済のS3APIは,

  • GetService: 現存するBucketをリスト
  • PutBucket: Bucketを作る
  • GetBucket: Bucketの中に入ってるオブジェクトをリスト
  • PutObject: Bucketの中にオブジェクトを入れる
  • GetObject: オブジェクトを読み出す

です. ファイルシステムでいうと, mkdir, ls, read/writeくらいが実装出来たことになります. 基本的な処理は出来るようになったと言うことが出来ます.

finchは, ほとんどのAPIサーバを書くために十分な機能を持っているためおすすめです (日本のウェブ業界でfinch使ってるところはあるんでしょうか?使ってください!!)

  test("add buckets") { p =>
    import p._

    client.createBucket("myb1")
    client.createBucket("myb2")
    val res = client.listBuckets
    assert(res.forall(_.getOwner.getId === TestUsers.hoge.id))
    assert(Set(res(0).getName, res(1).getName) === Set("myb1", "myb2"))
    assert(res.size === 2)

    // location
    // val loc = cli.getBucketLocation("mybucket1")
    // assert(loc == "US")
  }

  test("put and get object") { p =>
    import p._

    client.createBucket("a.b")
    val f = getTestFile("test.txt")
    val putRes = client.putObject("a.b", "myobj.txt", f)
    assert(putRes.getVersionId === "null")

    val obj1 = client.getObject("a.b", "myobj.txt")
    checkFileContent(obj1, f)

    // test second read
    val obj2 = client.getObject("a.b", "myobj.txt")
    checkFileContent(obj2, f)
  }

  test("put and get image object") { p =>
    import p._

    client.createBucket("myb")
    val f = getTestFile("test.jpg")
    client.putObject("myb", "myobj", f)
    val obj = client.getObject("myb", "myobj")
    checkFileContent(obj, f)
  }

  test("put and get several objects") { p =>
    import p._

    client.createBucket("myb")
    val f = getTestFile("test.txt")
    client.putObject("myb", "myobj1", f)
    client.putObject("myb", "myobj2", f)
    val objListing = client.listObjects("myb")
    assert(objListing.getBucketName == "myb")
    val summaries = objListing.getObjectSummaries
    assert(summaries.size === 2)
    assert(summaries(0).getOwner.getId === TestUsers.hoge.id)

    val obj1 = client.getObject("myb", "myobj1")
    checkFileContent(obj1, f)
    val obj2 = client.getObject("myb", "myobj2")
    checkFileContent(obj2, f)
  }

次は, DeleteObjectや, S3の目玉であるMultipart Uploadを実装していきます. 認証については, v2/v4の両方を実装する予定であり, Presigned Requestも実装する予定ですが, 重要なところから作っていきます. (重要なところに着手することになった時にコードが複雑になっていると, 開発はうまくいかないので, どういう順序で実装するかは重要です)

akashic-storageは, S3の機能を色々と実装する予定ですが, たぶん実装しないものもあります.

  • PostObject: finchはこのリクエストを扱うのが苦手そうなのと, formの中を読み解かないとリクエスターのIDがわからないなどイレギュラーなので, 実装上かなりめんどくさいです. 実際にPostObjectをやるくらいならばPresigned Requestを発行しても同じようなことが出来ますから, PostObjectはたぶん実装しません.
  • CORS (Options Object): これは重要なのですが, S3の前にCORSを担当するプロキシを置くという運用でカバーすることも出来ると思うので, 優先度は低いです. CORSの処理を実装したパッケージ自体は持っているのですが, 自分でメンテするよりは他の人が作ったライブラリを使いたいです (minioはそうしています)
  • anonymousユーザ: anonymousユーザをサポートしようとすると実装が不必要に複雑化します. 基本的なユースケースとしてanonymousで使うということはあり得ないのと, 他人にファイルを見せる時には, ACLをAllUserにするよりはPresigned Requestを使うでしょうから, あんまり使われないものにソフトウェアを穢されるのも癪ですし, たぶん実装しません.

実装もそうですが, ドキュメントも必要ですし, 初期ユーザが試せるような基盤も構築する必要があります. まだまだやることはたくさんあって大変です. でもがんばります. minioの対抗馬がいてもいいと思うんです.