この記事は…

集え、初老丸達よ。初老丸達による世界に向けた技術的(又はそれに関連する)な物語を綴るカレンダーです。我こそ初老丸という方、初老丸予備軍の方も奮ってご参加下さい。ジーク・初老丸!

qiita.com

初老丸 Advent Calendar 2017 18 日目の記事です.

はじめに

fake-s3 とは…

fake-s3 - A lightweight server clone of Amazon S3 that simulates most of the commands supported by S3 with minimal dependencies

qiita.com

Amazon S3 の API レスポンスをお手軽に返してくれるサーバーで, gem で提供されていますが, 以下のようにコマンドラインからサーバーを起動することが出来るようです.

fakes3 -r /mnt/fakes3_root -p 4567

今回はコンテナで起動する予定なので, コマンドラインからの起動については触れない予定です.

コンテナで立ち上げられると良い(と思っている)

Docker イメージが提供されているので, 以下のようにコンテナを起動することで, お手軽に利用可能です.

docker run --name oreno-s3 -p 4569:4569 -d lphoward/fake-s3

curl でアクセスしてみると, 以下のように出力されました.

$ curl 127.0.0.1:4569
<?xml version="1.0" encoding="UTF-8"?><ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>123</ID><DisplayName>FakeS3</DisplayName></Owner><Buckets><Bucket><Name>oreno-bucket-1</Name><CreationDate>2017-12-17T05:30:20.000Z</CreationDate></Bucket><Bucket><Name>oreno-bucket-2</Name><CreationDate>2017-12-17T05:30:42.000Z</CreationDate></Bucket><Bucket><Name>oreno-bucket-3</Name><CreationDate>2017-12-17T05:30:53.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>

ex_aws から利用する

以下のように利用した

ex_aws からだと config/config.ex は以下のように設定することで利用出来ました. ちなみに, fake-s3 の wiki にも Elixir での利用方法が書かれていました.

config :ex_aws,
  s3: [
    scheme: "http://",
    region: "ap-northeast-1",
    access_key_id: "xxxxxxxxxxxxxxxxxxxxx",
    secret_access_key: "xxxxxxxxxxxxxxxxxxxxx",
    host: %{"ap-northeast-1" => "127.0.0.1"},
    port: 4569
  ],
  debug_requests: true

iex から ExAws.S3.listbucket を叩いてみると, 以下のように fake-s3 に作って置いたバケットの一覧を取得することが出来ました.

iex(9)> ExAws.S3.list_buckets |> ExAws.request! |> Map.get(:body) |> Map.get(:buckets) |> Poison.encode!
"[{\"name\":\"oreno-bucket-1\",\"creation_date\":\"2017-12-17T05:30:42.000Z\"},{\"name\":\"oreno-bucket-2\",\"creation_date\":\"2017-12-17T05:30:43.000Z\"},{\"name\":\"oreno-bucket-3\",\"creation_date\":\"2017-12-17T05:30:44.000Z\"}]"

いい感じです.

せっかくなので, ExUnit から利用する

とある関数を作った

defmodule S3Ope do
  def get_bucket_list do
    ExAws.S3.list_buckets
      |> ExAws.request!
      |> Map.get(:body)
      |> Map.get(:buckets)
      |> bucket_list([])
  end

  defp bucket_list([head | tail], names) do
    %{"name": json_name} = head
    added_names = [json_name] ++ names
    bucket_list(tail, added_names)
  end

  defp bucket_list([], names), do: names
end

バケットの一覧をリストで返す関数.

iex で実行すると以下のように出力されるだけです.

iex(1)> S3Ope.get_bucket_list
["oreno-bucket-3", "oreno-bucket-2", "oreno-bucket-1"]

fake-s3 を利用してテスト

以下のようなテストを書きました.

defmodule S3OpeTest do
  use ExUnit.Case

  setup_all do
    ExAws.S3.put_bucket('test-bucket', 'ap-northeast-1') |> ExAws.request!
    :ok
    # これが fake-s3 だと動かない...fake-s3 の delete_bucket がアレ
    on_exit fn ->
      ExAws.S3.delete_bucket('test-bucket') |> ExAws.request!
    end
  end

  test "バケット名が List 型で出力されること." do
    assert S3Ope.get_bucket_list() == ["test-bucket"]
  end
end

テストを実行

いい感じです.

$ mix test --trace

S3OpeTest
  * test バケット名が List 型で出力されること. (107.2ms)


Finished in 0.3 seconds
1 test, 0 failures

Randomized with seed 254576

以上

ちょっと気になる

バケットを削除しようとすると, エラーになるので色々と調べてみると, 以下のように見た目は削除に成功してもバケットリストを取得出来てしまうという状態を確認しています. 引続き調査しようと思っています.

とは言え

fake-s3 を使えば, 実際の S3 にアクセスすること無く, S3 を操作するツールの検証が出来るので一家に一台は入れておいて良いツールだと思います.

元記事はこちら

fake-s3 を使ってみた(ExUnit から利用してみる例)