add example/update readmes
AWS-Zig Build / build-zig-0.11.0-amd64-host (push) Successful in 8m58s Details

This commit is contained in:
Emil Lerch 2023-09-05 18:30:42 -07:00
parent 090c06c403
commit c3944edf43
Signed by: lobo
GPG Key ID: A7B62D657EF764F8
6 changed files with 478 additions and 15 deletions

View File

@ -32,6 +32,7 @@ jobs:
- run: zig build -Dtarget=riscv64-linux
- run: zig build -Dtarget=x86_64-macos
- run: zig build -Dtarget=aarch64-macos
- run: ( cd example && zig build ) # Make sure example builds
# Zig package manager expects everything to be inside a directory in the archive,
# which it then strips out on download. So we need to shove everything inside a directory
# the way GitHub/Gitea does for repo archives

301
README.md
View File

@ -26,34 +26,39 @@ Building
files from upstream AWS Go SDK v2, run the code generation, then build the main
project with the generated code. Testing can be done with `zig test`.
Note that there are some loose ends on this version as compared to the [0.9.0
branch](https://git.lerch.org/lobo/aws-sdk-for-zig/src/branch/0.9.0). More
details below in Limitations. This branch overall is superior, as is the 0.11
compiler, but if you need an edge case and don't want to issue a PR, feel free
to use that branch.
Using
-----
This is designed for use with the Zig 0.11 package manager, and exposes a module
called "aws". Set up `build.zig.zon` and add the dependency/module to your project
as normal and the package manager should do its thing.
as normal and the package manager should do its thing. A full example can be found
in [/example](example/README.md).
Running the demo
----------------
Configuring the module and/or Running the demo
----------------------------------------------
This library mimics the aws c libraries for it's work, so it operates like most
other 'AWS things'. main.zig gives you a handful of examples for working with services.
For local testing or alternative endpoints, there's no real standard, so
there is code to look for `AWS_ENDPOINT_URL` environment variable that will
supersede all other configuration. Note that an alternative endpoint may
require passing in a client option to specify an different TLS root certificate
(pass null to disable certificate verification).
other 'AWS things'. [/src/main.zig](src/main.zig) gives you a handful of examples
for working with services. For local testing or alternative endpoints, there's
no real standard, so there is code to look for `AWS_ENDPOINT_URL` environment
variable that will supersede all other configuration.
Other branches
--------------
The default branch is fully functional but requires TLS 1.3. Until AWS Services
support TLS 1.3 at the end of 2023, the [0.9.0 branch](https://git.lerch.org/lobo/aws-sdk-for-zig/src/branch/0.9.0)
may be of use. More details below in limitations. This branch overall is
superior, as is the 0.11 compiler, but if you need a service that doesn't support
TLS 1.3 and you need it right away, feel free to use that branch. Note I do not
intend to update code in the 0.9.0 branch, but will accept PRs.
An [old branch based on aws-crt](https://github.com/elerch/aws-sdk-for-zig/tree/aws-crt) exists
for posterity, and supports x86_64 linux. The old branch is deprecated, so if
there are issues you see that work correctly in the aws-crt branch, please
file an issue.
file an issue. I can't think of a reason to use this branch any more. I do not
intend to entertain PRs on this branch, but reach out if you think it is important.
Limitations
-----------
@ -85,3 +90,269 @@ TODO List:
Compiler wishlist/watchlist:
* [comptime allocations](https://github.com/ziglang/zig/issues/1291) so we can read files, etc (or is there another way)
Services with TLS 1.3 Support (115 services)
--------------------------------------------
```
acm
amplify
apigateway
apigateway
appconfig
application-autoscaling
applicationinsights
apprunner
appstream2
appsync
athena
backup
batch
cloud9
clouddirectory
cloudformation
cloudhsmv2
cloudsearch
cloudtrail
events
codeartifact
codebuild
codedeploy
codeguru-profiler
codepipeline
codestar-connections
comprehend
comprehendmedical
compute-optimizer
dms
databrew
dataexchange
datasync
devicefarm
directconnect
ds
ec2-instance-connect
api.ecr
api.ecr-public
ecs
elasticfilesystem
es
elastictranscoder
elasticmapreduce
events
finspace
finspace-api
fms
frauddetector
fsx
gamelift
glacier
globalaccelerator
glue
healthlake
honeycode
identitystore
inspector
iot
iotanalytics
iotevents
data.iotevents
api.iotwireless
ivs
kafka
kendra
kinesisanalytics
kms
lakeformation
license-manager
lookoutvision
metering.marketplace
mediaconnect
medialive
mediapackage-vod
mediastore
mgh
network-firewall
networkmanager
opsworks-cm
personalize
pinpoint
email
sms-voice.pinpoint
polly
qldb
session.qldb
quicksight
rds-data
redshift-data
rekognition
tagging
route53resolver
s3-outposts
api.sagemaker
edge.sagemaker
secretsmanager
servicecatalog
servicediscovery
servicequotas
email
states
snowball
ssm-contacts
swf
textract
transcribe
transfer
translate
waf-regional
workdocs
workmail
workmailmessageflow
workspaces
xray
```
Services without TLS 1.3 support (140 services)
-----------------------------------------------
```
access-analyzer
acm-pca
amplifybackend
execute-api
appflow
app-integrations
application-cost-profiler
discovery
appmesh
auditmanager
autoscaling
autoscaling-plans
budgets
chime
cloudfront
cloudsearchdomain
monitoring
logs
codecommit
codeguru-reviewer
codestar
codestar-notifications
cognito-identity
cognito-idp
cognito-sync
config
connect
contact-lens
participant.connect
ce
profile
datapipeline
dax
api.detective
devops-guru
dlm
dynamodb
streams.dynamodb
ebs
ec2
eks
elasticache
elasticbeanstalk
api.elastic-inference
elasticloadbalancing
emr-containers
firehose
fis
forecast
forecastquery
greengrass
groundstation
guardduty
health
iam
imagebuilder
devices.iot1click
projects.iot1click
data.iot
api.iotdeviceadvisor
api.fleethub.iot
data.jobs.iot
api.tunneling.iot
iotsitewise
iotthingsgraph
kinesis
kinesisvideo
lambda
models.lex
models-v2-lex
runtime.lex
runtime-v2-lex
lightsail
geo
lookoutequipment
lookoutmetrics
machinelearning
macie
macie2
managedblockchain
catalog.marketplace
marketplacecommerceanalytics
entitlement.marketplace
mediaconvert
mediapackage
data.mediastore
api.mediatailor
PlaybackEndpointPrefix
mgn
migrationhub-config
mobile
mq
mturk-requester
airflow
rds
nimble
opsworks
organizations
outposts
personalize-events
personalize-runtime
pi
api.pricing
ram
rds
redshift
resource-groups
robomaker
route53
route53domains
s3
s3-control
a2i-runtime.sagemaker
featurestore-runtime.sagemaker
runtime.sagemaker
savingsplans
schemas
securityhub
serverlessrepo
servicecatalog-appregistry
shield
signer
sms
sns
sqs
ssm
ssm-incidents
portal.sso
sso
oidc
storagegateway
sts
support
synthetics
query.timestream
ingest.timestream
waf
wafv2
wellarchitected
worklink
```

32
example/README.md Normal file
View File

@ -0,0 +1,32 @@
Example usage of aws-zig module by a client application
=======================================================
This directory has a fully functional command line application that utilizes
the aws-zig module using the Zig package manager introduced in Zig 0.11.
A couple things of note:
* Rather than the typical "we will use the source code repository archive",
you will notice in build.zig.zon that the dependency URL is a Gitea actions
artifact. This is due to the fact that the aws service models are generated,
and the package manager does not currently (I think) have a way to perform
compile steps when pulling in a package and using a module. In any case, this
seems like a reasonable restriction. The aws-zig SDK repository will build
and test each code change, along with model generation, then capture the
generated files along with the actual SDK source code and upload the resulting
artifact for use. To find the correct artifact, look at the [actions page](https://git.lerch.org/lobo/aws-sdk-for-zig/actions)
and choose a run ([example](https://git.lerch.org/lobo/aws-sdk-for-zig/actions/runs/57)).
Under Artifacts, you will see the tarball and can paste that link into `build.zig.zon`.
* The action naming is incorrect according to the zig naming guidelines. This
will be fixed in the code generation process shortly, and this example will be
updated accordingly.
* Many (most) AWS services still don't support TLS 1.3. I recommend using
[mitmproxy](https://mitmproxy.org) during development. Otherwise, it is
likely best to wait until service(s) important to you are supported on
TLS 1.3.
Usage
-----
After configuring your AWS credentials using the standard tools, a simple
`zig build run` should be sufficient to run this example.

82
example/build.zig Normal file
View File

@ -0,0 +1,82 @@
const std = @import("std");
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "tmp",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// const smithy_dep = b.dependency("smithy", .{
// // These are the two arguments to the dependency. It expects a target and optimization level.
// .target = target,
// .optimize = optimize,
// });
// exe.addModule("smithy", smithy_dep.module("smithy"));
const aws_dep = b.dependency("aws", .{
// These are the two arguments to the dependency. It expects a target and optimization level.
.target = target,
.optimize = optimize,
});
exe.addModule("aws", aws_dep.module("aws"));
// This declares intent for the executable to be installed into the
// standard location when the user invokes the "install" step (the default
// step when running `zig build`).
b.installArtifact(exe);
// This *creates* a Run step in the build graph, to be executed when another
// step is evaluated that depends on it. The next line below will establish
// such a dependency.
const run_cmd = b.addRunArtifact(exe);
// By making the run step depend on the install step, it will be run from the
// installation directory rather than directly from within the cache directory.
// This is not necessary, however, if the application depends on other installed
// files, this ensures they will be present and in the expected location.
run_cmd.step.dependOn(b.getInstallStep());
// This allows the user to pass arguments to the application in the build
// command itself, like this: `zig build run -- arg1 arg2 etc`
if (b.args) |args| {
run_cmd.addArgs(args);
}
// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build run`
// This will evaluate the `run` step rather than the default, which is "install".
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const unit_tests = b.addTest(.{
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
const run_unit_tests = b.addRunArtifact(unit_tests);
// Similar to creating the run step earlier, this exposes a `test` step to
// the `zig build --help` menu, providing a way for the user to request
// running the unit tests.
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_unit_tests.step);
}

15
example/build.zig.zon Normal file
View File

@ -0,0 +1,15 @@
.{
.name = "myapp",
.version = "0.0.1",
.dependencies = .{
.aws = .{
.url = "https://git.lerch.org/lobo/aws-sdk-for-zig/actions/runs/57/artifacts/27",
.hash = "1220c054e4ff05072b0eda6a2ab318cffe3a9356d70e0ec116e55835bf5e5c9baafd",
},
.smithy = .{
.url = "https://git.lerch.org/lobo/smithy/archive/41b61745d25a65817209dd5dddbb5f9b66896a99.tar.gz",
.hash = "122087deb0ae309b2258d59b40d82fe5921fdfc35b420bb59033244851f7f276fa34",
},
},
}

62
example/src/main.zig Normal file
View File

@ -0,0 +1,62 @@
const std = @import("std");
const aws = @import("aws");
pub const std_options = struct {
pub const log_level: std.log.Level = .info;
// usually log_level is enough, but log_scope_levels can be used
// for finer grained control
pub const log_scope_levels = &[_]std.log.ScopeLevel{
.{ .scope = .awshttp, .level = .warn },
};
};
pub fn main() anyerror!void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const stdout_raw = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_raw);
defer bw.flush() catch unreachable;
const stdout = bw.writer();
// To use a proxy, uncomment the following with your own configuration
// const proxy = std.http.Proxy{
// .protocol = .plain,
// .host = "localhost",
// .port = 8080,
// };
//
// var client = aws.Client.init(allocator, .{ .proxy = proxy });
var client = aws.Client.init(allocator, .{});
defer client.deinit();
const options = aws.Options{
.region = "us-west-2",
.client = client,
};
// As of 2023-08-28, only ECS from this list supports TLS v1.3
// AWS commitment is to enable all services by 2023-12-31
const services = aws.Services(.{ .sts, .kms }){};
try stdout.print("Calling KMS ListKeys, a TLS 1.3 enabled service\n", .{});
try stdout.print("You likely have at least some AWS-generated keys in your account,\n", .{});
try stdout.print("but if the account has not had many services used, this may return 0 keys\n\n", .{});
const call_kms = try aws.Request(services.kms.list_keys).call(.{}, options);
try stdout.print("\trequestId: {s}\n", .{call_kms.response_metadata.request_id});
try stdout.print("\tkey count: {d}\n", .{call_kms.response.keys.?.len});
for (call_kms.response.keys.?) |key| {
try stdout.print("\t\tkey id: {s}\n", .{key.key_id.?});
try stdout.print("\t\tkey arn: {s}\n", .{key.key_arn.?});
}
defer call_kms.deinit();
try stdout.print("\n\n\nCalling STS GetCallerIdentity. This does not have TLS 1.3 in September 2023\n", .{});
try stdout.print("A failure may occur\n\n", .{});
const call = try aws.Request(services.sts.get_caller_identity).call(.{}, options);
defer call.deinit();
try stdout.print("\tarn: {s}\n", .{call.response.arn.?});
try stdout.print("\tid: {s}\n", .{call.response.user_id.?});
try stdout.print("\taccount: {s}\n", .{call.response.account.?});
try stdout.print("\trequestId: {s}\n", .{call.response_metadata.request_id});
}