Giter Club home page Giter Club logo

smithy-rs's Introduction

Smithy Rust CI on Branch main

Smithy code generators for Rust that generate clients, servers, and the entire AWS SDK. The latest unreleased SDK build can be found in aws-sdk-rust/next.

Design documentation

All internal and external interfaces are considered unstable and subject to change without notice.

Setup

  1. ./gradlew will setup gradle for you. JDK 17 is required.
  2. Running tests requires a working Rust installation. See Rust docs for installation instructions on your platform. The MSRV (Minimum Supported Rust Version) for the crates in this project is stable-2, i.e. the current stable Rust version and the prior two versions. Older versions may work.

Development

For development, pre-commit hooks make it easier to pass automated linting when opening a pull request. Setup:

brew install pre-commit # (or appropriate for your platform: https://pre-commit.com/)
pre-commit install

Project Layout

  • aws: AWS specific codegen & Rust code (signing, endpoints, customizations, etc.) Common commands:
    • ./gradlew :aws:sdk:assemble: Generate (but do not test / compile etc.) a fresh SDK into sdk/build/aws-sdk
    • ./gradlew :aws:sdk:sdkTest: Generate & run all tests for a fresh SDK. (Note that these tests require Go to be installed for FIP support to compile properly)
    • ./gradlew :aws:sdk:{cargoCheck, cargoTest, cargoDocs, cargoClippy}: Generate & run specified cargo command.
  • codegen-core: Common code generation logic useful for clients and servers
  • codegen-client: Whitelabel Smithy client code generation
  • codegen-client-test: Smithy protocol test generation & integration tests for Smithy client whitelabel code
  • design: Design documentation. See the design/README.md for details about building / viewing.
  • codegen-server: Whitelabel Smithy server code generation
  • codegen-server-test: Smithy protocol test generation & integration tests for Smithy server whitelabel code
  • examples: A collection of server implementation examples

Testing

Running all of smithy-rs's tests can take a very long time, so it's better to know which parts to test based on the changes being made, and allow continuous integration to find other issues when posting a pull request.

In general, the components of smithy-rs affect each other in the following order (with earlier affecting later):

  1. rust-runtime
  2. codegen and codegen-server
  3. aws/rust-runtime
  4. aws/sdk-codegen

Some components, such as codegen-client-test and codegen-server-test, are purely for testing other components.

Testing rust-runtime and aws/rust-runtime

To test the rust-runtime crates:

# Run all Rust tests for `rust-runtime/` (from repo root):
cargo test --manifest-path=rust-runtime/Cargo.toml
# Run clippy for `rust-runtime/` (from repo root):
cargo clippy --manifest-path=rust-runtime/Cargo.toml

# Or
cd rust-runtime
cargo test
cargo clippy

To test the aws/rust-runtime crates:

# Run all Rust tests for `aws/rust-runtime/` (from repo root):
cargo test --manifest-path=aws/rust-runtime/Cargo.toml
# Run clippy for `aws/rust-runtime/` (from repo root):
cargo clippy --manifest-path=aws/rust-runtime/Cargo.toml

# Or
cd aws/rust-runtime
cargo test
cargo clippy

Some runtime crates have a additional-ci script that can also be run. These scripts often require cargo-hack and cargo-udeps to be installed.

Testing Client/Server Codegen

To test the code generation, the following can be used:

# Run Kotlin codegen unit tests
./gradlew codegen-core:check
./gradlew codegen-client:check
./gradlew codegen-server:check
# Run client codegen tests
./gradlew codegen-client-test:check
# Run server codegen tests
./gradlew codegen-server-test:check

Several Kotlin unit tests generate Rust projects and compile them. When these fail, they typically output links to the location of the generated code so that it can be inspected.

To look at generated code when the codegen tests fail, check these paths depending on the test suite that's failing:

  • For codegen-client-test: codegen-client-test/build/smithyprojections/codegen-client-test
  • For codegen-server-test: codegen-server-test/build/smithyprojections/codegen-server-test

Testing SDK Codegen

See the readme in aws/sdk/ for more information about these targets as they can be configured to generate more or less AWS service clients.

# Run Kotlin codegen unit tests
./gradlew aws:sdk-codegen:check
# Generate an SDK, but do not attempt to compile / run tests. Useful for inspecting generated code
./gradlew :aws:sdk:assemble
# Run all the tests
./gradlew :aws:sdk:sdkTest
# Validate that the generated code compiles
./gradlew :aws:sdk:cargoCheck
# Validate that the generated code passes Clippy
./gradlew :aws:sdk:cargoClippy
# Validate the generated docs
./gradlew :aws:sdk:cargoDoc

The generated SDK will be placed in aws/sdk/build/aws-sdk.

smithy-rs's People

Contributors

82marbag avatar aajtodd avatar alistaim avatar aws-sdk-rust-ci avatar benesch avatar crisidev avatar david-perez avatar davidogunsaws avatar doug-aws avatar drganjoo avatar eagletmt avatar eduardomourar avatar guymguym avatar hlbarber avatar jdisanti avatar jjant avatar kiiadi avatar landonxjames avatar lmjw avatar lukemathwalker avatar mcmasn-amzn avatar milesziemer avatar rcoh avatar rschmitt avatar shinglyu avatar thomas-k-cameron avatar unexge avatar velfi avatar weihanglo avatar ysaito1001 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smithy-rs's Issues

Waiters design

Could be deferred although figuring how how they fit into the API needs to happen soon than later

Dynamo Integration tests

DynamoDB integration tests that run against localdynamo—for now, these will use Hyper & a faker signer. The thing we actually want to exercise is the serialization & deserialization layers

Support reserved words

Smithy allows fields to be named things that are reserved words in Rust like as. Currently, this will generate code that won't compile.

Base Config generation

Generate initial config objects for services. From the Smithy side, this is only going to contain idempotency control

Event stream protocol implementation

  • Event Stream frame encoding/decoding (#609)
  • http::Response -> operation::Response refactoring in smithy-http (#635)
  • Refactor sigv4 to sign arbitrary data rather than http::Request
  • Track the initial signature in the property bag
  • Rust implementation for Event Stream sender in input
  • Rust implementation for Event Stream receiver in output
  • Codegen
    • Event Stream input sender w/ signing
    • Event Stream output receiver
    • Event Stream traits
    • Selection of HTTP protocol version via Smithy traits (e.g., @restXml)
      • Current service models aren't using these correctly, and some operations actually require HTTP 1 for bidirectional event streaming
      • For now: error out if there's an operation that doesn't specify HTTP 2 for bidirectional streaming, and customize models for known bad operations to specify HTTP 2
    • Events marked with @error are terminal; should filter them out of the event stream union and handle them as actual SdkErrors
    • Make Event Stream recv() errors compatible with other SdkErrors when using the ? operator
    • Non-HTTP bound protocols like AWS JSON send initial members as a struct embedded in a first event frame
    • Generate new error type for Event Stream recv() since it's not 1-to-1 with the operation errors
  • Testing
    • Record bidirectional traffic against all supported protocols:
      • restJson1
      • awsJson1 and awsJson1_1
      • awsQuery
      • ec2Query
      • restXml
    • Exercise all event stream header types
    • Exercise all event stream payload types (blob, string, struct, union)
    • Write replay tests
  • Test the developer experience when the Event Stream input stream yields an error (where does the error go?)

Documentation Rev2

The docs as they come out of Smithy have a number of shortcomings:

  • They are mostly HTML, which, while technically markdown is very hard to read in code
  • They don't respect rustdoc's first-line-is-the-header convention which leads to docs which are either missing headers or have too much in the header
  • The <code>FooInput</code> that is used can't use rustdocs links unless we parse that out and reparent it to an actual thing.
  • Since we are renaming Exception to Error, if we continue to do that, we must also update the docs
  • Cargo.toml description field cannot have Markdown in it
  • Rustdoc for Rust 1.53 requires bare links to be surrounded by angle brackets (e.g., <https://github.com> rather than https://github.com)
  • Generate code examples for operations that have no required args

Support optional URI elements

Currently, the Rust code generator assumes that all members with the httpLabel trait are required. This isn't always true. For example, S3's GetObjectRequest structure binds partNumber to a URI element, but it's necessarily optional since it's only accepted when retrieving a single part of a multi-part object. As is, the generated code forces this field to be specified in all requests.

I'd say "just examine the member for the required trait," but I sadly don't see many models using it. FWIW, The AWS service models bundled with botocore appear to correctly model all required members regardless of where they appear on the wire. Are these service definitions hand-maintained?

Endpoint Support

  • Endpoint trait support
  • Basic AWS endpoint implementation
  • endpoints.json dynamic resolver generation
  • Design endpoint discovery
  • Endpoint discovery implementation

Consider Exception renaming strategy

The current strategy of the Rust SDK is to rename Exception to Error and Error to Error_ (to prevent conflicts with a similarly named Exception.

While this strategy is sound, it's worth a discussion about whether it's a thing we want to do.

Sensitive trait support

Needs to be backwards compatible to add and remove, which I think means that a custom debug implementation is probably required.

Another option large design option could be making all fields private and using accessors.

This would allow us to have a string accessor even though the underlying type was Sensitive

Waiters implementation

  • Design/RFC developer experience
  • Implement Jmespath Smithy shape traversal (#3526)
  • Code generate waiters and hook into existing retry strategy

CI jobs

Automated CI jobs. Should run on pull requests.

  • Codegen tests pass
  • Integration tests pass
  • Ktlint passes
  • < 5 minutes to finish

HTTP Error protocol tests

These tests should target the operation shape and use the #61 to ensure the correct type of error is deserialized

Feedback for Generated Code

As requested by @rcoh; here are few things I've noticed from reading the documentation.

  • dynamo::model::FailureException is the only type in the model module that represents an error. I think this happened because the underlying Smithy definition might be incorrect.
    • Generally speaking, I don't think that "Exception" shouldn't appear in any Rust code
  • The operation module is noisy from the builder module [appendix one]. It also hides the actual input operations below the documentation's fold. Unfortunately, applying #[doc(hidden)] to a module applies to all nested modules and exports, which means that the builder options are hidden: rust-lang/rust#59368
  • When documenting input structs, consider using the operation's documentation instead of the input object's documentation [appendix two]. Input structs are the customer's entrypoint to the service, not the operation itself. With a sans-io interface, there's no place to document operations, which often serve as the why of a service's operation.
  • The separate impl blocks for inputs without different generic bounds feel off to me [appendix three]. I'd unify the two.
    • I'm not sure that an assemble associated function is necessary for non-streaming operations, but I believe this relates to the (somewhat) open design question around (de)serialization.
  • Intra-doc links don't resolve to a URL. You might need to define a [docs-url] in the root of each crate: tokio-rs/tracing#1078 (comment).
    • Consider using the tokio-rs/tracing repo as an example for documentation configuration. Members of the rustdoc team have use tokio-rs/tracing as a testbed for unstable features.

Appendix

Appendix One

Screen Shot 2020-11-24 at 10 51 36 AM

Appendix Two

Screen Shot 2020-11-24 at 10 54 58 AM

Appendix Three

Screen Shot 2020-11-24 at 11 06 05 AM

Create trivial access to request IDs for all SDK responses

Request ids are returned in different locations in each protocol (eg. headers, JSON body, XML body etc.).

As an end customer, it should be straightforward to extract that request id from any given response.

  • Make it trivial to access the request ID programmatically
  • Add a tracing::debug! or tracing::debug_span! somewhere in the AWS middleware to attach the request ID to logs

Aws Json 1.1 Tracking Issue

Tracking issue for AwsJson 1.1 support

AwsJson1.1 is done when the protocol tests pass for serialization and deserialization

  • Support recursive structures (#6)
  • Document type support (#31)
  • Error deserializer support

Design XML serialization

Do we use serde with renames? Do we do something more complex? Do we need our own aws-xml-serde?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.