-
Notifications
You must be signed in to change notification settings - Fork 55
chore: add documentation and example #90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
add3a00
c9bc98a
5c88223
41ed35c
eddd504
fb3d795
1c89d9f
5578d95
cc9c950
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Changelog | ||
|
|
||
| ## [Unreleased] | ||
|
|
||
| ## [0.1.0-M0] - 03/19/2021 | ||
|
|
||
| **WARNING: Beta releases may contain bugs and no guarantee is made about API stability. They are not recommended for production use!** | ||
|
|
||
| This is the initial beta release of AWS SDK Kotlin. It represents an early look at the overall API surface. | ||
|
|
||
|
|
||
| See the [Getting Started Guide](docs/GettingStarted.md) for how to work with beta releases and examples. | ||
|
|
||
|
|
||
| ### Services in this release | ||
|
|
||
| * DynamoDB | ||
| * Polly | ||
| * Translate | ||
| * Cognito Identity Provider | ||
| * Secrets Manager | ||
| * NOTE: Default idempotency token provider will not currently work, you'll need to override the config to create or update secrets until [#180](https://github.com/awslabs/smithy-kotlin/issues/180) is implemented | ||
| * KMS | ||
| * Lambda | ||
|
|
||
| NOTES: | ||
| * We currently can (theoretically) support any JSON based AWS protocol. If there is a service you would like to see added in a future release (before developer preview) please reach out and let us know. | ||
| * No customizations are currently implemented, some SDK's may not behave 100% correctly without such support. | ||
| * Retries, waiters, paginators, and other features are not yet implemented | ||
|
|
||
| ### Features | ||
| * Coroutine API | ||
| * DSL Builders | ||
| * Default (environment or config) or static credential providers only. Additional providers will be added in later releases. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps this is CDO instincts but would seem better just to mention what's provided and not allude to what/when will come next, for credential providers and platform support.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, but we don't have a clean public/internal roadmap yet so I think trying to provide a bit about what's missing to head off questions might be in order.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's reasonable. The platform support line (one below) I guess is the one I'm concerned with. Maybe rewording to imply what platforms are supported without giving hints as to when other platform support will come would be a better way to manage expectations. Something like |
||
| * JVM only support (multiplatform support is on the roadmap) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| # Beta Release Quickstart | ||
|
|
||
| Beta releases of the AWS Kotlin SDK are published as a complete maven local repository with all associated dependencies. | ||
|
|
||
|
|
||
| 1. Download the [latest release](https://github.com/awslabs/aws-sdk-kotlin/releases) from Github | ||
|
|
||
| 2. Unzip the repository somewhere on your local machine | ||
|
|
||
| ```sh | ||
| > unzip aws-sdk-kotlin-0.1.0-M0.zip | ||
| ``` | ||
|
|
||
| There should be a folder named `aws-sdk-kotlin-repo` | ||
|
|
||
| 3. Add the local repository to your Gradle or Maven configuration | ||
|
|
||
| #### Gradle Users | ||
|
|
||
| ```kt | ||
| # file: my-project/build.gradle.kts | ||
|
|
||
|
|
||
| repositories { | ||
| maven { | ||
| name = "kotlinSdkLocal" | ||
| url = uri("/path/to/aws-sdk-kotlin-repo/m2") | ||
| } | ||
| mavenCentral() | ||
| } | ||
| ``` | ||
|
|
||
| #### Maven Users | ||
| ```xml | ||
| <project> | ||
| ... | ||
| <repositories> | ||
| <repository> | ||
| <id>kotlinSdkLocal</id> | ||
| <name>Beta AWS Kotlin SDK Repo</name> | ||
| <url>/path/to/aws-sdk-kotlin-repo/m2</url> | ||
| </repository> | ||
| </repositories> | ||
| ... | ||
| </project> | ||
|
|
||
| ``` | ||
|
|
||
|
|
||
| 4. Add services to your project | ||
|
|
||
| ```kt | ||
|
|
||
| val awsKotlinSdkVersion = "0.1.0-M0" | ||
| // OR put it in gradle.properties | ||
| // val awsKotlinSdkVersion by project | ||
|
|
||
| dependencies { | ||
| implementation(kotlin("stdlib")) | ||
| implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3") | ||
|
|
||
| implementation("aws.sdk.kotlin:dynamodb:$awsKotlinSdkVersion") | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
| 4. Checkout the `examples` directory | ||
|
|
||
|
|
||
| ## Giving Feedback | ||
|
|
||
| * Slack - Join #aws-sdk-kotlin-interest to share feedback and get updates on SDK development | ||
| * Submit [issues](https://github.com/awslabs/aws-sdk-kotlin/issues) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| plugins { | ||
| kotlin("jvm") version "1.4.31" | ||
| } | ||
|
|
||
| allprojects { | ||
| group = "aws.sdk.kotlin.example" | ||
| version = "1.0-SNAPSHOT" | ||
|
|
||
| repositories { | ||
| maven { | ||
| name = "kotlinSdkLocal" | ||
| url = uri(TODO("set your local repository path")) | ||
| // e.g. | ||
| //url = uri("file:///tmp/aws-sdk-kotlin-repo/m2") | ||
| } | ||
| mavenCentral() | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| plugins { | ||
| kotlin("jvm") | ||
| } | ||
|
|
||
| val awsSdkKotlinVersion: String by project | ||
|
|
||
| dependencies { | ||
| implementation(kotlin("stdlib")) | ||
| implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3") | ||
| implementation("aws.sdk.kotlin:dynamodb:$awsSdkKotlinVersion") | ||
| implementation("com.google.code.gson:gson:2.8.6") | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| /* | ||
| * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * SPDX-License-Identifier: Apache-2.0. | ||
| */ | ||
| package aws.sdk.kotlin.example | ||
|
|
||
| import aws.sdk.kotlin.runtime.AwsServiceException | ||
| import aws.sdk.kotlin.services.dynamodb.DynamodbClient | ||
| import aws.sdk.kotlin.services.dynamodb.model.* | ||
| import com.google.gson.JsonElement | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment there may be suitable KMP JSON parsers we could use here, with the benefit being when we are ready to test or provide for eval on JS or native, the example code should work unaltered.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well ideally we provide such an API so that users don't need to add another dependency: smithy-lang/smithy-kotlin#243 |
||
| import com.google.gson.JsonParser | ||
| import kotlinx.coroutines.delay | ||
| import kotlinx.coroutines.runBlocking | ||
| import java.lang.IllegalStateException | ||
|
|
||
| /** | ||
| * Partial implementation of: https://docs.amazonaws.cn/en_us/amazondynamodb/latest/developerguide/GettingStarted.Java.html | ||
| */ | ||
| fun main() = runBlocking { | ||
| val client = DynamodbClient { region = "us-east-2" } | ||
|
|
||
| val tableName = "dynamo-movies-example" | ||
|
|
||
| try { | ||
| createMoviesTable(client, tableName) | ||
|
|
||
| client.waitForTableReady(tableName) | ||
|
|
||
| loadMoviesTable(client, tableName) | ||
|
|
||
| val films2222 = client.moviesInYear(tableName, 2222) | ||
| check(films2222.count == 0) | ||
|
|
||
| val films2013 = client.moviesInYear(tableName, 2013) | ||
| check(films2013.count == 2) | ||
|
|
||
| val titles = films2013.items?.mapNotNull { (it["title"] as? AttributeValue.S)?.value } | ||
| println("2013 film titles:") | ||
| println(titles) | ||
| } catch (ex: AwsServiceException) { | ||
| println(ex) | ||
| } | ||
|
|
||
| client.close() | ||
| } | ||
|
|
||
| suspend fun createMoviesTable(client: DynamodbClient, name: String) { | ||
| val tableExists = client.listTables(ListTablesRequest {}).tableNames?.contains(name) ?: false | ||
| if (tableExists) return | ||
|
|
||
| val req = CreateTableRequest { | ||
| tableName = name | ||
| keySchema = listOf( | ||
| KeySchemaElement { | ||
| attributeName = "year" | ||
| keyType = KeyType.Hash | ||
| }, | ||
| KeySchemaElement { | ||
| attributeName = "title" | ||
| keyType = KeyType.Range | ||
| } | ||
| ) | ||
|
|
||
| attributeDefinitions = listOf( | ||
| AttributeDefinition { | ||
| attributeName = "year" | ||
| attributeType = ScalarAttributeType.N | ||
| }, | ||
| AttributeDefinition { | ||
| attributeName = "title" | ||
| attributeType = ScalarAttributeType.S | ||
| } | ||
| ) | ||
| provisionedThroughput { | ||
| readCapacityUnits = 10 | ||
| writeCapacityUnits = 10 | ||
| } | ||
| } | ||
|
|
||
| val resp = client.createTable(req) | ||
| println("created table: ${resp.tableDescription?.tableArn}") | ||
| } | ||
|
|
||
| // no waiters support (yet) | ||
| suspend fun DynamodbClient.waitForTableReady(name: String) { | ||
| while (true) { | ||
| try { | ||
| val req = DescribeTableRequest { tableName = name } | ||
| if (describeTable(req).table?.tableStatus != TableStatus.Creating) { | ||
| println("table ready") | ||
| return | ||
| } | ||
| } catch (ex: AwsServiceException) { | ||
| if (!ex.isRetryable) throw ex | ||
| } | ||
| println("waiting for table to be ready...") | ||
| delay(1000) | ||
| } | ||
| } | ||
|
|
||
| suspend fun loadMoviesTable(client: DynamodbClient, name: String) { | ||
| // load items into table | ||
| val data = getResourceAsText("data.json") | ||
| val elements = JsonParser.parseString(data).asJsonArray | ||
| elements.forEach { | ||
| // map the json element -> AttributeValue | ||
| val attrValue = jsonElementToAttributeValue(it) as? AttributeValue.M ?: throw IllegalStateException("expected a top level object value") | ||
| val req = PutItemRequest { | ||
| tableName = name | ||
| item = attrValue.value | ||
| } | ||
|
|
||
| client.putItem(req) | ||
| } | ||
| } | ||
|
|
||
| suspend fun DynamodbClient.moviesInYear(name: String, year: Int): QueryResponse { | ||
| val req = QueryRequest { | ||
| tableName = name | ||
| keyConditionExpression = "#yr = :yyyy" | ||
| expressionAttributeNames = mapOf( | ||
| "#yr" to "year" | ||
| ) | ||
| expressionAttributeValues = mapOf( | ||
| ":yyyy" to AttributeValue.N(year.toString()) | ||
| ) | ||
| } | ||
| return query(req) | ||
| } | ||
|
|
||
| // utility/support functions | ||
|
|
||
| fun getResourceAsText(path: String): String = | ||
| object {}.javaClass.getResource(path).readText() | ||
|
|
||
| // map json to attribute values | ||
| fun jsonElementToAttributeValue(element: JsonElement): AttributeValue = when { | ||
| element.isJsonNull -> AttributeValue.NULL(true) | ||
| element.isJsonPrimitive -> { | ||
| val primitive = element.asJsonPrimitive | ||
| when { | ||
| primitive.isBoolean -> AttributeValue.BOOL(primitive.asBoolean) | ||
| primitive.isString -> AttributeValue.S(primitive.asString) | ||
| else -> { | ||
| check(primitive.isNumber) { "expected number" } | ||
| AttributeValue.N(primitive.asString) | ||
| } | ||
| } | ||
| } | ||
| element.isJsonArray -> AttributeValue.L(element.asJsonArray.map(::jsonElementToAttributeValue)) | ||
| element.isJsonObject -> { | ||
| AttributeValue.M( | ||
| element.asJsonObject.entrySet().associate { | ||
| it.key to jsonElementToAttributeValue(it.value) | ||
| } | ||
| ) | ||
| } | ||
| else -> throw IllegalStateException("unknown json element type: $element") | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| [ | ||
| { | ||
| "year": 2013, | ||
| "title": "Turn It Down, Or Else!", | ||
| "info": { | ||
| "directors": [ | ||
| "Alice Smith", | ||
| "Bob Jones" | ||
| ], | ||
| "release_date": "2013-01-18T00:00:00Z", | ||
| "rating": 6.2, | ||
| "genres": [ | ||
| "Comedy", | ||
| "Drama" | ||
| ], | ||
| "image_url": "http://ia.media-imdb.com/images/N/O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg", | ||
| "plot": "A rock band plays their music at high volumes, annoying the neighbors.", | ||
| "rank": 11, | ||
| "running_time_secs": 5215, | ||
| "actors": [ | ||
| "David Matthewman", | ||
| "Ann Thomas", | ||
| "Jonathan G. Neff" | ||
| ] | ||
| } | ||
| }, | ||
| { | ||
| "year": 2013, | ||
| "title": "Rush", | ||
| "info": { | ||
| "directors": [ | ||
| "Ron Howard" | ||
| ], | ||
| "release_date": "2013-09-02T00:00:00Z", | ||
| "rating": 8.3, | ||
| "genres": [ | ||
| "Action", | ||
| "Biography", | ||
| "Drama", | ||
| "Sport" | ||
| ], | ||
| "image_url": "http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg", | ||
| "plot": "A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.", | ||
| "rank": 2, | ||
| "running_time_secs": 7380, | ||
| "actors": [ | ||
| "Daniel Bruhl", | ||
| "Chris Hemsworth", | ||
| "Olivia Wilde" | ||
| ] | ||
| } | ||
| } | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
|
|
||
| # AWS SDK | ||
| awsSdkKotlinVersion=0.1.0-M0 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question
Perhaps it's forthcoming but is there some build file which is specifying these services go into a zip?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
our internal gitfarm repo has more info