Powered by AppSignal & Oban Pro

Bunnyx: Storage

livebooks/storage.livemd

Bunnyx: Storage

StorageZone CRUD + edge storage file operations.

Setup

Mix.install([{:bunnyx, path: Path.join(__DIR__, "..")}])

api_key = System.fetch_env!("LB_BUNNY_API_KEY")
client = Bunnyx.new(api_key: api_key, receive_timeout: 60_000)
run_id = System.system_time(:second) |> rem(100_000) |> to_string()
sz_name = "bunnyx-int-sz-#{run_id}"

IO.puts("Client ready. Zone: #{sz_name}")
:ok

Cleanup

{:ok, all} = Bunnyx.StorageZone.list(client)
all = if is_list(all), do: all, else: all.items

for z <- Enum.filter(all, &amp;String.starts_with?(&amp;1.name, "bunnyx-int-sz-")) do
  case Bunnyx.StorageZone.delete(client, z.id) do
    {:ok, _} -> IO.puts("  Deleted: #{z.name}")
    {:error, e} -> IO.puts("  Failed: #{z.name} (#{e.message})")
  end
end

IO.puts("✓ Cleanup done")

StorageZone.check_availability

{:ok, true} = Bunnyx.StorageZone.check_availability(client, sz_name)

IO.puts("✓ check_availability: #{sz_name} is available")

StorageZone.create

{:ok, sz} = Bunnyx.StorageZone.create(client, name: sz_name, region: "DE")
%Bunnyx.StorageZone{} = sz
^sz_name = sz.name
true = is_integer(sz.id)
true = is_binary(sz.password)
true = sz.region == "DE"

IO.puts("✓ create: #{sz.id} (#{sz.name}, region: #{sz.region})")
sz

StorageZone.get

{:ok, fetched} = Bunnyx.StorageZone.get(client, sz.id)
%Bunnyx.StorageZone{} = fetched
true = fetched.id == sz.id
true = fetched.name == sz_name

IO.puts("✓ get: #{fetched.id} — matches")

StorageZone.list

{:ok, all} = Bunnyx.StorageZone.list(client)
all = if is_list(all), do: all, else: all.items
true = Enum.any?(all, &amp;(&amp;1.id == sz.id))

IO.puts("✓ list: found zone in #{length(all)} total")

StorageZone.update

{:ok, updated} = Bunnyx.StorageZone.update(client, sz.id, rewrite_404_to_200: true)
%Bunnyx.StorageZone{} = updated
true = updated.rewrite_404_to_200 == true

IO.puts("✓ update: rewrite_404_to_200 set to true")

StorageZone.statistics

{:ok, stats} = Bunnyx.StorageZone.statistics(client, sz.id)
true = is_map(stats.storage_used_chart)
true = is_map(stats.file_count_chart)

IO.puts("✓ statistics: returned")

StorageZone.reset_password

{:ok, nil} = Bunnyx.StorageZone.reset_password(client, sz.id)

# Re-fetch to get the new password
{:ok, sz} = Bunnyx.StorageZone.get(client, sz.id)

IO.puts("✓ reset_password: done (new password length: #{String.length(sz.password)})")

StorageZone.reset_read_only_password

{:ok, nil} = Bunnyx.StorageZone.reset_read_only_password(client, sz.id)

IO.puts("✓ reset_read_only_password: done")

Edge Storage: put, get, list, delete

# Wait for credentials to propagate
IO.puts("  Waiting for credential propagation...")
Process.sleep(5_000)

storage = Bunnyx.Storage.new(storage_key: sz.password, zone: sz_name)
content = "Hello from Bunnyx integration test!"

# Put
{:ok, nil} = Bunnyx.Storage.put(storage, "/test.txt", content)
IO.puts("✓ Storage.put: uploaded /test.txt")

# Get
{:ok, downloaded} = Bunnyx.Storage.get(storage, "/test.txt")
^content = downloaded
IO.puts("✓ Storage.get: content matches")

# List
{:ok, objects} = Bunnyx.Storage.list(storage, "/")
true = is_list(objects)
file = Enum.find(objects, &amp;(&amp;1.object_name == "test.txt"))
%Bunnyx.Storage.Object{} = file
true = file.length > 0
IO.puts("✓ Storage.list: found #{file.object_name} (#{file.length} bytes)")

# Put with checksum
checksum = :crypto.hash(:sha256, "checksum test") |> Base.encode16(case: :lower)
{:ok, nil} = Bunnyx.Storage.put(storage, "/checksum.txt", "checksum test", checksum: checksum)
IO.puts("✓ Storage.put (checksum): uploaded with SHA-256")

# Delete
{:ok, nil} = Bunnyx.Storage.delete(storage, "/test.txt")
IO.puts("✓ Storage.delete: /test.txt deleted")

{:ok, nil} = Bunnyx.Storage.delete(storage, "/checksum.txt")
IO.puts("✓ Storage.delete: /checksum.txt deleted")

StorageZone.delete

{:ok, nil} = Bunnyx.StorageZone.delete(client, sz.id)
{:error, %Bunnyx.Error{}} = Bunnyx.StorageZone.get(client, sz.id)

IO.puts("✓ delete: zone #{sz.id} gone")

Done

IO.puts("")
IO.puts("══════════════════════════════════════")
IO.puts("  Storage: all passed!")
IO.puts("  StorageZone CRUD ✓  Statistics ✓")
IO.puts("  Password reset ✓  Availability ✓")
IO.puts("  Edge Storage put/get/list/delete ✓")
IO.puts("  Checksum upload ✓")
IO.puts("══════════════════════════════════════")