Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions CHANGELOG.md
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
Copy link
Contributor

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?

Copy link
Contributor Author

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

* 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.
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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 Kotlin platforms supported in this release: JVM

* JVM only support (multiplatform support is on the roadmap)
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# AWS SDK for Kotlin


## License

This library is licensed under the Apache 2.0 License.


## Getting Started

See the [Getting Started Guide](docs/GettingStarted.md)


## Development

### Generate SDK(s)
Expand Down
5 changes: 3 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ dependencies {

val lintPaths = listOf(
"codegen/smithy-aws-kotlin-codegen/**/*.kt",
"client-runtime/**/*.kt"
"client-runtime/**/*.kt",
"examples/**/*.kt"
)

tasks.register<JavaExec>("ktlint") {
Expand All @@ -48,4 +49,4 @@ tasks.register("showRepos") {
println("All repos:")
println(repositories.map { it.name })
}
}
}
73 changes: 73 additions & 0 deletions docs/GettingStarted.md
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)
21 changes: 21 additions & 0 deletions examples/build.gradle.kts
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()
}
}



12 changes: 12 additions & 0 deletions examples/dynamodb-movies/build.gradle.kts
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
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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"
]
}
}
]
4 changes: 4 additions & 0 deletions examples/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

# AWS SDK
awsSdkKotlinVersion=0.1.0-M0

Binary file added examples/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
Loading