aws-mumu

Crates.ioaws-mumu
lib.rsaws-mumu
version0.1.0
created_at2025-08-15 12:18:54.507997+00
updated_at2025-08-15 12:18:54.507997+00
descriptionaws-mumu is a plugin for the mumu ecosystem
homepagehttps://lava.nu11.uk
repositoryhttps://gitlab.com/tofo/aws-mumu
max_upload_size
id1796655
size147,812
(justifiedmumu)

documentation

README

MuMu × AWS (S3) Plugin

A lightweight extension that adds Amazon S3 capabilities to the MuMu runtime: credentials sessions, bucket creation, and object fetching (to file or as a streaming iterator). Built-in SigV4 signing, friendly error surfaces, and examples for both real S3 and S3‑compatible endpoints (e.g., LocalStack).

Language:RustRuntime:MuMuAuth:SigV4Transport:reqwest (blocking)

Table of contents

  1. Highlights
  2. Quick start
  3. Usage
  4. API reference
  5. How it works
  6. Repository layout
  7. LocalStack tips
  8. Troubleshooting
  9. Security
  10. License
  11. Acknowledgements

Highlights

  • 🔐 Session‑based credentials via aws:credentials(…) (no global state; returns a short session id)
  • ✍️ SigV4 signing in pure Rust (src/functions/sigv4.rs)
  • 🪣 Create bucket: aws:s3:create_bucket(…)
  • ⬇️ Fetch object: save to file (path/folder) or stream as a MuMu InkIterator
  • 🧯 Robust errors: dynamic calls catch panics and return [ok: false, error: "…"]

Quick start

1) Build the plugin

The MuMu loader looks for a dynamic library named libmumu.{so|dylib} (Linux/macOS) or .dll (Windows). For this plugin, base is aws, so you’ll get libmumuaws.so, libmumuaws.dylib, or mumuaws.dll.

# from the repository root
cargo build --release

# point MuMu to the build directory (adjust for your OS/shell)
export MUMU_PLUGIN_PATH="$(pwd)/target/release"

2) Run MuMu (REPL or script)

# REPL (verbose is handy while developing)
mumu --verbose
# or (depending on install)
lava-mumu --verbose

# Run a .mu script
mumu examples/s3/fetch.mu

3) Load the plugin and configure credentials

extend("aws")
extend("process")  // to read environment variables

credentials = aws:credentials([
  accessKeyId:     process:env("AWS_ACCESS_KEY_ID"),
  secretAccessKey: process:env("AWS_SECRET_ACCESS_KEY"),
  region:          process:env("AWS_REGION"),
  // Optional: S3-compatible endpoint (e.g., LocalStack)
  // endpoint: "http://localhost:4566"
])

Return value: a short session id string — pass this to other AWS calls.

Usage

Create a bucket

extend("aws")
extend("process")
extend("test")  // just for test:diceware()

credentials = aws:credentials([
  accessKeyId:     process:env("AWS_ACCESS_KEY_ID"),
  secretAccessKey: process:env("AWS_SECRET_ACCESS_KEY"),
  region:          process:env("AWS_REGION"),
  endpoint:        "http://localhost:4566"  // optional
])

result = aws:s3:create_bucket([
  credentials: credentials,
  bucket:      test:diceware()
])

slog(result)  // → [ok: true, bucket: "..."] or [ok: false, error: "..."]

Fetch an object — save to disk

extend("aws")
extend("process")

credentials = aws:credentials([
  accessKeyId:     process:env("AWS_ACCESS_KEY_ID"),
  secretAccessKey: process:env("AWS_SECRET_ACCESS_KEY"),
  region:          process:env("AWS_REGION")
])

result = aws:s3:fetch([
  credentials: credentials,
  bucket:      "my-bucket",
  key:         "path/to/object.png",
  // use either:
  // path: "/tmp/object.png",
  folder:      "/tmp/s3-downloads"  // filename inferred from key
])

slog(result)  // → [ok: true, path: "/tmp/s3-downloads/object.png"]

Fetch an object — stream chunks

Omit path/folder to get an InkIterator yielding chunks: { chunk: IntArray }.

extend("aws")
extend("file")
extend("process")

credentials = aws:credentials([
  accessKeyId:     process:env("AWS_ACCESS_KEY_ID"),
  secretAccessKey: process:env("AWS_SECRET_ACCESS_KEY"),
  region:          process:env("AWS_REGION")
])

stream = aws:s3:fetch([
  credentials: credentials,
  bucket:      "my-bucket",
  key:         "large-object.bin"
])

file:write("/tmp/large-object.bin", stream)

Chunks are read in up to 8192‑byte blocks and delivered as signed ints (0–255) in an IntArray. The iterator finishes naturally when the stream ends.

More streaming examples: examples/s3/fetch-stream.mu, examples/s3/fetch-stream-map.mu, examples/s3/fetch-multi.mu.

API reference

aws:credentials(opts)session_id:string

Key Type Required Notes
accessKeyId string Yes AWS access key id
secretAccessKey string Yes AWS secret
region string Yes e.g., us-east-1
endpoint string No S3‑compatible endpoint (LocalStack, MinIO w/ S3 API, etc.)

Validates inputs and stores an in‑memory session. Returns a short session id. On failure, the dynamic wrapper surfaces an error object:

[ok: false, error: "aws:credentials: ..."]

aws:s3:create_bucket(opts){ ok, bucket? , error? }

Key Type Required Notes
credentials string Yes Session id from aws:credentials
bucket string Yes Bucket name

On success returns [ok: true, bucket: "…"]; on error returns [ok: false, error: "…"].

aws:s3:fetch(opts)InkIterator or { ok, path? , error? }

Key Type Required Notes
credentials string Yes Session id
bucket string Yes Bucket name
key string Yes Object key
path string No Full destination path (direct download)
folder string No Destination directory (filename inferred)
  • If path or folder is provided → downloads the object and returns [ok: true, path: "..."].
  • If neither is provided → returns a streaming InkIterator of chunks { chunk: IntArray }.

How it works

  • Session store: SESSIONS (lazy static HashMap<String, AwsSession>) keyed by session id. (src/register/credentials.rs)
  • SigV4: canonical request + hex SHA‑256 + HMAC chain; returns ready‑to‑use headers (including Authorization). (src/functions/sigv4.rs)
  • Networking: reqwest::blocking client. Direct download writes to a file; streaming spawns a reader thread that sends 8 KiB blocks over an MPSC channel to a MuMu plugin iterator. (src/register/s3_fetch.rs)
  • Error model: all dynamic functions are guarded with catch_unwind; failures are returned as keyed arrays, never raw panics.

Repository layout

LOCAL/
  src/
    functions/
      sigv4.rs
    register/
      credentials.rs
      s3_create_bucket.rs
      s3_fetch.rs
      hello.rs
  examples/
    s3/
      create-bucket.mu
      fetch.mu
      fetch-multi.mu
      fetch-stream.mu
      fetch-stream-map.mu
REMOTE/ (MuMu engine; vendored)
  src/
    parser/...   # lexer, parser, interpreter, eval helpers, etc.
    modules/...  # extend, compose/pipe, slog/sput, ink, include, type

The vendored MuMu engine includes improvements for λ by‑reference semantics, composition, numeric coercions, REPL input, autocompletion, and statement write‑through to reference cells.

LocalStack tips

  1. Run LocalStack with S3 enabled (e.g., via Docker).

  2. Use test credentials and set

    endpoint
    

    in

    aws:credentials
    

    :

    credentials = aws:credentials([
      accessKeyId:     "test",
      secretAccessKey: "test",
      region:          "us-east-1",
      endpoint:        "http://localhost:4566"
    ])
    
  3. Use the same APIs as you would for AWS.

Troubleshooting

  • “no session with id …” — The session id is missing or stale. Call aws:credentials again and reuse its return value.

  • “AWS error status …” — Check bucket permissions, region, and the exact bucket/key. For S3‑compatible endpoints ensure the endpoint is set in aws:credentials.

  • Plugin not found

    — Ensure

    MUMU_PLUGIN_PATH

    includes the directory with the compiled library. The loader also searches near the MuMu binary and common system locations:

    • Current exe dir and ../lib
    • CWD: ./libmumuaws.* or ./aws/libmumuaws.*
    • Linux: /usr/local/lib, /usr/lib64, /usr/lib
    • macOS: /usr/local/lib, /opt/homebrew/lib
    • Windows: %ProgramFiles%\lava-mumu\lib

Security

  • Sessions are in‑memory only; no persistence.
  • Prefer process:env("…") for secrets; avoid hard‑coding.
  • Use S3‑compatible stacks (e.g., LocalStack) for development and tests.

License

MuMu engine files reference the MIT license in headers. If this plugin has a separate license, consult the repository’s LICENSE. Example files are provided for educational use.

Acknowledgements

Thanks to the MuMu contributors for the runtime, REPL, and libraries. This plugin follows MuMu’s dynamic function conventions (extend("aws")) and uses InkIterator for streaming downloads.


© 2025 MuMu × AWS Plugin

Commit count: 0

cargo fmt