Skip to content
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

feat(appsync): add RDS datasource #9258

Merged
merged 28 commits into from
Nov 2, 2020
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ae8b5b0
added rds datasource for appsync
kochie Jul 24, 2020
ce78424
fixed tests for appsync
kochie Jul 28, 2020
8cb1ba5
Merge remote-tracking branch 'upstream/master'
kochie Jul 28, 2020
3de36b7
Merge branch 'master' into master
kochie Jul 29, 2020
105ccbc
added examples in README
kochie Jul 29, 2020
94dac4f
Merge branch 'master' into master
kochie Jul 30, 2020
876485e
Update packages/@aws-cdk/aws-appsync/README.md
kochie Aug 4, 2020
b972518
Update packages/@aws-cdk/aws-appsync/README.md
kochie Aug 4, 2020
fa55177
Update packages/@aws-cdk/aws-appsync/README.md
kochie Aug 4, 2020
c8a9996
Merge branch 'master' into master
kochie Aug 4, 2020
a6f5fe9
Merge remote-tracking branch 'upstream/master'
BryanPan342 Aug 20, 2020
8c56bcf
adjust code-base to reflect master
BryanPan342 Aug 20, 2020
5d06daf
remove integ test because unncessary
BryanPan342 Aug 20, 2020
0e26fa2
update readme
BryanPan342 Aug 20, 2020
4690249
Merge branch 'master' into master
BryanPan342 Aug 25, 2020
40e2c1c
gosh darnit
BryanPan342 Aug 25, 2020
ddef9fe
Merge github.com:aws/aws-cdk
kochie Oct 17, 2020
be3bf96
Merge branch 'master' into master
kochie Oct 17, 2020
a2a6d3a
fixed README conflict
kochie Oct 17, 2020
d38a2a4
Merge branch 'master' into master
kochie Oct 18, 2020
656db0e
fixed build issues
kochie Oct 19, 2020
8b72a69
fixed appsync tests
kochie Oct 19, 2020
8663f67
Apply suggestions from code review
kochie Oct 19, 2020
c8736df
Update README.md
kochie Oct 19, 2020
bac0575
Merge branch 'master' into master
kochie Oct 19, 2020
8c9108d
Merge branch 'master' into master
kochie Oct 28, 2020
6772209
Merge branch 'master' into master
kochie Oct 30, 2020
ee00839
Merge branch 'master' into master
mergify[bot] Nov 2, 2020
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
65 changes: 64 additions & 1 deletion packages/@aws-cdk/aws-appsync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type demo {
version: String!
}
type Query {
getDemos: [ test! ]
getDemos: [ demo! ]
}
input DemoInput {
version: String!
Expand Down Expand Up @@ -84,6 +84,69 @@ demoDS.createResolver({
});
```

## Aurora Serverless

AppSync provides a data source for executing SQL commands against Amazon Aurora
Serverless clusters. You can use AppSync resolvers to execute SQL statements
against the Data API with GraphQL queries, mutations, and subscriptions.

```ts
// Create username and password secret for DB Cluster
const secret = new rds.DatabaseSecret(stack, 'AuroraSecret', {
username: 'clusteradmin',
});

// Create the DB cluster, provide all values needed to customise the database.
const cluster = new rds.DatabaseCluster(stack, 'AuroraCluster', {
engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_07_1 }),
credentials: { username: 'clusteradmin' },
clusterIdentifier: 'db-endpoint-test',
defaultDatabaseName: 'demos',
});

// Build a data source for AppSync to access the database.
const rdsDS = api.addRdsDataSource('rds', 'The rds data source', cluster, secret);

// Set up a resolver for an RDS query.
rdsDS.createResolver({
typeName: 'Query',
fieldName: 'getDemosRds',
requestMappingTemplate: MappingTemplate.fromString(`
{
"version": "2018-05-29",
"statements": [
"SELECT * FROM demos"
]
}
`),
responseMappingTemplate: MappingTemplate.fromString(`
$util.rds.toJsonObject($ctx.result)
`),
});

// Set up a resolver for an RDS mutation.
rdsDS.createResolver({
typeName: 'Mutation',
fieldName: 'addDemoRds',
requestMappingTemplate: MappingTemplate.fromString(`
{
"version": "2018-05-29",
"statements": [
"INSERT INTO demos VALUES (:id, :version)",
"SELECT * WHERE id = :id"
],
"variableMap": {
":id": $util.toJson($util.autoId()),
":version": $util.toJson($ctx.args.version)
}
}
`),
responseMappingTemplate: MappingTemplate.fromString(`
$util.rds.toJsonObject($ctx.result)
`),
});
```

#### HTTP Endpoints
GraphQL schema file `schema.graphql`:

Expand Down
58 changes: 56 additions & 2 deletions packages/@aws-cdk/aws-appsync/lib/data-source.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ITable } from '@aws-cdk/aws-dynamodb';
import { IGrantable, IPrincipal, IRole, Role, ServicePrincipal } from '@aws-cdk/aws-iam';
import { Grant, IGrantable, IPrincipal, IRole, Role, ServicePrincipal } from '@aws-cdk/aws-iam';
import { IFunction } from '@aws-cdk/aws-lambda';
import { IResolvable } from '@aws-cdk/core';
import { IDatabaseCluster } from '@aws-cdk/aws-rds';
import { ISecret } from '@aws-cdk/aws-secretsmanager';
import { IResolvable, Stack } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnDataSource } from './appsync.generated';
import { IGraphqlApi } from './graphqlapi-base';
Expand Down Expand Up @@ -283,4 +285,56 @@ export class LambdaDataSource extends BackedDataSource {
});
props.lambdaFunction.grantInvoke(this);
}
}

/**
* Properties for an AppSync RDS datasource
*/
export interface RdsDataSourceProps extends BackedDataSourceProps {
/**
* The database cluster to call to interact with this data source
*/
readonly databaseCluster: IDatabaseCluster;
/**
* The secret containing the credentials for the database
*/
readonly secretStore: ISecret;
}

/**
* An AppSync datasource backed by RDS
*/
export class RdsDataSource extends BackedDataSource {
constructor(scope: Construct, id: string, props: RdsDataSourceProps) {
super(scope, id, props, {
type: 'RELATIONAL_DATABASE',
relationalDatabaseConfig: {
rdsHttpEndpointConfig: {
awsRegion: props.databaseCluster.stack.region,
dbClusterIdentifier: props.databaseCluster.clusterIdentifier,
awsSecretStoreArn: props.secretStore.secretArn,
},
relationalDatabaseSourceType: 'RDS_HTTP_ENDPOINT',
BryanPan342 marked this conversation as resolved.
Show resolved Hide resolved
},
BryanPan342 marked this conversation as resolved.
Show resolved Hide resolved
});
props.secretStore.grantRead(this);
const clusterArn = Stack.of(this).formatArn({
service: 'rds',
resource: `cluster:${props.databaseCluster.clusterIdentifier}`,
});
// Change to grant with RDS grant becomes implemented
Grant.addToPrincipal({
grantee: this,
actions: [
'rds-data:DeleteItems',
'rds-data:ExecuteSql',
'rds-data:ExecuteStatement',
'rds-data:GetItems',
'rds-data:InsertItems',
'rds-data:UpdateItems',
],
resourceArns: [clusterArn, `${clusterArn}:*`],
scope: this,
});
}
}
41 changes: 40 additions & 1 deletion packages/@aws-cdk/aws-appsync/lib/graphqlapi-base.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ITable } from '@aws-cdk/aws-dynamodb';
import { IFunction } from '@aws-cdk/aws-lambda';
import { IDatabaseCluster } from '@aws-cdk/aws-rds';
import { ISecret } from '@aws-cdk/aws-secretsmanager';
import { CfnResource, IResource, Resource } from '@aws-cdk/core';
import { DynamoDbDataSource, HttpDataSource, LambdaDataSource, NoneDataSource, AwsIamConfig } from './data-source';
import { DynamoDbDataSource, HttpDataSource, LambdaDataSource, NoneDataSource, RdsDataSource, AwsIamConfig } from './data-source';

/**
* Optional configuration for data sources
Expand Down Expand Up @@ -90,6 +92,21 @@ export interface IGraphqlApi extends IResource {
*/
addLambdaDataSource(id: string, lambdaFunction: IFunction, options?: DataSourceOptions): LambdaDataSource;

/**
* add a new Rds data source to this API
*
* @param id The data source's id
* @param databaseCluster The database cluster to interact with this data source
* @param secretStore The secret store that contains the username and password for the database cluster
* @param options The optional configuration for this data source
*/
addRdsDataSource(
id: string,
databaseCluster: IDatabaseCluster,
secretStore: ISecret,
options?: DataSourceOptions
): RdsDataSource;

/**
* Add schema dependency if not imported
*
Expand Down Expand Up @@ -178,6 +195,28 @@ export abstract class GraphqlApiBase extends Resource implements IGraphqlApi {
});
}

/**
* add a new Rds data source to this API
* @param id The data source's id
* @param databaseCluster The database cluster to interact with this data source
* @param secretStore The secret store that contains the username and password for the database cluster
* @param options The optional configuration for this data source
*/
public addRdsDataSource(
id: string,
databaseCluster: IDatabaseCluster,
secretStore: ISecret,
options?: DataSourceOptions,
): RdsDataSource {
return new RdsDataSource(this, id, {
api: this,
name: options?.name,
description: options?.description,
databaseCluster,
secretStore,
});
}

/**
* Add schema dependency if not imported
*
Expand Down
6 changes: 6 additions & 0 deletions packages/@aws-cdk/aws-appsync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@
"dependencies": {
"@aws-cdk/aws-cognito": "0.0.0",
"@aws-cdk/aws-dynamodb": "0.0.0",
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-rds": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-secretsmanager": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/core": "0.0.0",
Expand All @@ -92,10 +95,13 @@
"peerDependencies": {
"@aws-cdk/aws-cognito": "0.0.0",
"@aws-cdk/aws-dynamodb": "0.0.0",
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/aws-rds": "0.0.0",
"@aws-cdk/aws-secretsmanager": "0.0.0",
"constructs": "^3.2.0"
},
"engines": {
Expand Down
Loading