vantage-aws 0.4.1

AWS API persistence backend for Vantage framework — incubating
Documentation

vantage-aws

AWS API backend for the Vantage data framework — incubating.

Treats AWS JSON-1.1 RPC endpoints (CloudWatch Logs, ECS, DynamoDB control plane, KMS, …) as Vantage TableSources. AwsAccount is the source — there's no per-operation wrapper. The operation you want to run lives in the table name.

Authentication

Three ways to construct an AwsAccount, plus a chain helper:

use vantage_aws::AwsAccount;

let aws = AwsAccount::new(access_key, secret_key, region);   // explicit
let aws = AwsAccount::from_env()?;                            // standard env vars
let aws = AwsAccount::from_credentials_file()?;               // ~/.aws/credentials [default] only
let aws = AwsAccount::from_default()?;                        // env first, file fallback

from_credentials_file reads only the [default] profile. Region falls through AWS_REGIONAWS_DEFAULT_REGION~/.aws/config [default] region. AWS_PROFILE, SSO, assume-role, IMDS — out of v0; set the env vars yourself if you need anything fancier.

Quick start

use vantage_aws::{AwsAccount, eq};
use vantage_table::table::Table;
use vantage_types::EmptyEntity;
use vantage_dataset::prelude::ReadableValueSet;

let aws = AwsAccount::from_default()?;

let mut groups: Table<AwsAccount, EmptyEntity> = Table::new(
    "logGroups:logs/Logs_20140328.DescribeLogGroups",
    aws,
);
groups.add_condition(eq("logGroupNamePrefix", "/aws/lambda/"));

let rows = groups.list_values().await?;

That's a CloudWatch DescribeLogGroups call, filtered by prefix. The condition folds into the JSON request body; the response array gets parsed into Record<CborValue> rows.

Anatomy of a table name

"logGroups:logs/Logs_20140328.DescribeLogGroups"
    │       │       └── X-Amz-Target header value
    │       └────────── service code (also URL hostname segment)
    └────────────────── response field that holds the row array

You only have to write this once per resource — usually you wrap it in a model factory and forget about the encoding (see below).

Built-in models

vantage_aws::models ships ready-made tables so you don't have to memorise the table-name format:

  • CloudWatch Logs: log_groups_table, log_streams_table, log_events_table.
  • ECS (under models::ecs): clusters_table, services_table, tasks_table, task_definitions_table.
use vantage_aws::models::{log_groups_table, log_events_table};
use vantage_aws::eq;

let mut groups = log_groups_table(aws.clone());
groups.add_condition(eq("logGroupNamePrefix", "/aws/lambda/"));
let rows = groups.list_values().await?;

let mut events = log_events_table(aws);
events.add_condition(eq("logGroupName", "/aws/lambda/foo"));
let logs = events.list_values().await?;

log_groups_table registers two with_many relations — events and streams — that traverse to the group's log events / streams. AWS doesn't accept multi-value filters, so the source has to narrow to a single group before traversal — otherwise the call errors at execute time.

ECS APIs split into a List* step (returns ARNs only) and a Describe* step (full objects). v0 exposes the List* side; rows hold the ARN plus parsed-out short-name helpers (Cluster::name(), Task::task_id(), etc.).

Conditions

eq folds straight into the JSON request body. AWS APIs only accept exact-match filters, so that's all you really get:

use vantage_aws::eq;

table.add_condition(eq("logGroupNamePrefix", "/aws/lambda/"));

Bring AwsOperation into scope to write column.eq(...) instead:

use vantage_aws::AwsOperation;

table.add_condition(table["logGroupName"].clone().eq("/ecs/ba-nginx"));

In and Deferred are here to make with_one / with_many traversal work — they must collapse to a single value at execute time, otherwise the call errors loudly.

Demo CLI

examples/aws-cli.rs exercises the end-to-end machinery:

cargo run --example aws-cli -- list-groups
cargo run --example aws-cli -- list-groups --prefix /aws/lambda/
cargo run --example aws-cli -- list-events /ecs/ba-nginx
cargo run --example aws-cli -- traverse                        # with_many walk
cargo run --example aws-cli -- --region eu-west-2 list-groups  # override

Output goes through vantage_cli_util::print_table so it exercises the same Table / TableSource machinery the rest of the framework uses.

SigV4

No aws-sdk-*, no aws-sigv4 — signing is hand-rolled in src/sign.rs with hmac + sha2 + hex and pinned to AWS's canonical-example fixture. Non-streaming, non-presigned, JSON-1.1 only. If you need something else, you probably want a different crate.

Status

v0 covers: AwsAccount + JSON-1.1 transport, hand-rolled SigV4, Eq / In / Deferred conditions, with_one / with_many traversal, CloudWatch (LogGroup, LogStream, LogEvent) and ECS (Cluster, Service, Task, TaskDefinition) models, env-var and ~/.aws/credentials [default] credential loading.

Out of scope for v0:

  • Writes. insert_table_value and friends return errors. Read-only end-to-end.
  • Pagination. First page only. Most JSON-1.1 list operations cap at 50–100 items per call.
  • Aggregations. sum / min / max error out — would need a full scan.
  • REST-JSON / S3. Lambda invoke and S3 are different protocols; they'll arrive as their own crates.
  • AWS_PROFILE / SSO / assume-role / IMDS. Static credentials and the [default] profile only.

License

MIT OR Apache-2.0