Skip to content

Commit

Permalink
feat(appsync): add OpenSearch domain data source (#16529)
Browse files Browse the repository at this point in the history
Deprecate `ElasticsearchDataSource` and introduce `OpenSearchDataSource` as a replacement.

closes #16528

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
BenChaimberg authored Mar 11, 2022
1 parent a9e286e commit 922a9dc
Show file tree
Hide file tree
Showing 9 changed files with 554 additions and 26 deletions.
17 changes: 9 additions & 8 deletions packages/@aws-cdk/aws-appsync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,18 +240,19 @@ httpDs.createResolver({
});
```

### Elasticsearch
### Amazon OpenSearch Service

AppSync has builtin support for Elasticsearch from domains that are provisioned
through your AWS account. You can use AppSync resolvers to perform GraphQL operations
such as queries, mutations, and subscriptions.
AppSync has builtin support for Amazon OpenSearch Service (successor to Amazon
Elasticsearch Service) from domains that are provisioned through your AWS account. You can
use AppSync resolvers to perform GraphQL operations such as queries, mutations, and
subscriptions.

```ts
import * as es from '@aws-cdk/aws-elasticsearch';
import * as opensearch from '@aws-cdk/aws-opensearchservice';

const user = new iam.User(this, 'User');
const domain = new es.Domain(this, 'Domain', {
version: es.ElasticsearchVersion.V7_1,
const domain = new opensearch.Domain(this, 'Domain', {
version: opensearch.EngineVersion.OPENSEARCH_1_1,
removalPolicy: RemovalPolicy.DESTROY,
fineGrainedAccessControl: { masterUserArn: user.userArn },
encryptionAtRest: { enabled: true },
Expand All @@ -260,7 +261,7 @@ const domain = new es.Domain(this, 'Domain', {
});

declare const api: appsync.GraphqlApi;
const ds = api.addElasticsearchDataSource('ds', domain);
const ds = api.addOpenSearchDataSource('ds', domain);

ds.createResolver({
typeName: 'Query',
Expand Down
49 changes: 44 additions & 5 deletions packages/@aws-cdk/aws-appsync/lib/data-source.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ITable } from '@aws-cdk/aws-dynamodb';
import { IDomain } from '@aws-cdk/aws-elasticsearch';
import { IDomain as IElasticsearchDomain } from '@aws-cdk/aws-elasticsearch';
import { Grant, IGrantable, IPrincipal, IRole, Role, ServicePrincipal } from '@aws-cdk/aws-iam';
import { IFunction } from '@aws-cdk/aws-lambda';
import { IDomain as IOpenSearchDomain } from '@aws-cdk/aws-opensearchservice';
import { IServerlessCluster } from '@aws-cdk/aws-rds';
import { ISecret } from '@aws-cdk/aws-secretsmanager';
import { IResolvable, Lazy, Stack } from '@aws-cdk/core';
Expand Down Expand Up @@ -64,11 +65,18 @@ export interface ExtendedDataSourceProps {
*/
readonly dynamoDbConfig?: CfnDataSource.DynamoDBConfigProperty | IResolvable;
/**
* configuration for Elasticsearch Datasource
* configuration for Elasticsearch data source
*
* @deprecated - use `openSearchConfig`
* @default - No config
*/
readonly elasticsearchConfig?: CfnDataSource.ElasticsearchConfigProperty | IResolvable;
/**
* configuration for OpenSearch data source
*
* @default - No config
*/
readonly openSearchServiceConfig?: CfnDataSource.OpenSearchServiceConfigProperty | IResolvable;
/**
* configuration for HTTP Datasource
*
Expand Down Expand Up @@ -370,17 +378,21 @@ export class RdsDataSource extends BackedDataSource {
}

/**
* Properities for the Elasticsearch Data Source
* Properties for the Elasticsearch Data Source
*
* @deprecated - use `OpenSearchDataSourceProps` with `OpenSearchDataSource`
*/
export interface ElasticsearchDataSourceProps extends BackedDataSourceProps {
/**
* The elasticsearch domain containing the endpoint for the data source
*/
readonly domain: IDomain;
readonly domain: IElasticsearchDomain;
}

/**
* An Appsync datasource backed by Elasticsearch
*
* @deprecated - use `OpenSearchDataSource`
*/
export class ElasticsearchDataSource extends BackedDataSource {
constructor(scope: Construct, id: string, props: ElasticsearchDataSourceProps) {
Expand All @@ -394,4 +406,31 @@ export class ElasticsearchDataSource extends BackedDataSource {

props.domain.grantReadWrite(this);
}
}
}

/**
* Properties for the OpenSearch Data Source
*/
export interface OpenSearchDataSourceProps extends BackedDataSourceProps {
/**
* The OpenSearch domain containing the endpoint for the data source
*/
readonly domain: IOpenSearchDomain;
}

/**
* An Appsync datasource backed by OpenSearch
*/
export class OpenSearchDataSource extends BackedDataSource {
constructor(scope: Construct, id: string, props: OpenSearchDataSourceProps) {
super(scope, id, props, {
type: 'AMAZON_OPENSEARCH_SERVICE',
openSearchServiceConfig: {
awsRegion: props.domain.stack.region,
endpoint: `https://${props.domain.domainEndpoint}`,
},
});

props.domain.grantReadWrite(this);
}
}
38 changes: 33 additions & 5 deletions packages/@aws-cdk/aws-appsync/lib/graphqlapi-base.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ITable } from '@aws-cdk/aws-dynamodb';
import { IDomain } from '@aws-cdk/aws-elasticsearch';
import { IDomain as IElasticsearchDomain } from '@aws-cdk/aws-elasticsearch';
import { IFunction } from '@aws-cdk/aws-lambda';
import { IDomain as IOpenSearchDomain } from '@aws-cdk/aws-opensearchservice';
import { IServerlessCluster } 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, RdsDataSource, AwsIamConfig, ElasticsearchDataSource } from './data-source';
import { DynamoDbDataSource, HttpDataSource, LambdaDataSource, NoneDataSource, RdsDataSource, AwsIamConfig, ElasticsearchDataSource, OpenSearchDataSource } from './data-source';
import { Resolver, ExtendedResolverProps } from './resolver';

/**
Expand Down Expand Up @@ -114,11 +115,21 @@ export interface IGraphqlApi extends IResource {
/**
* add a new elasticsearch data source to this API
*
* @deprecated - use `addOpenSearchDataSource`
* @param id The data source's id
* @param domain The elasticsearch domain for this data source
* @param options The optional configuration for this data source
*/
addElasticsearchDataSource(id: string, domain: IDomain, options?: DataSourceOptions): ElasticsearchDataSource;
addElasticsearchDataSource(id: string, domain: IElasticsearchDomain, options?: DataSourceOptions): ElasticsearchDataSource;

/**
* Add a new OpenSearch data source to this API
*
* @param id The data source's id
* @param domain The OpenSearch domain for this data source
* @param options The optional configuration for this data source
*/
addOpenSearchDataSource(id: string, domain: IOpenSearchDomain, options?: DataSourceOptions): OpenSearchDataSource;

/**
* creates a new resolver for this datasource and API using the given properties
Expand Down Expand Up @@ -241,11 +252,12 @@ export abstract class GraphqlApiBase extends Resource implements IGraphqlApi {
/**
* add a new elasticsearch data source to this API
*
* @deprecated - use `addOpenSearchDataSource`
* @param id The data source's id
* @param domain The elasticsearch domain for this data source
* @param options The optional configuration for this data source
*/
public addElasticsearchDataSource(id: string, domain: IDomain, options?: DataSourceOptions): ElasticsearchDataSource {
public addElasticsearchDataSource(id: string, domain: IElasticsearchDomain, options?: DataSourceOptions): ElasticsearchDataSource {
return new ElasticsearchDataSource(this, id, {
api: this,
name: options?.name,
Expand All @@ -254,6 +266,22 @@ export abstract class GraphqlApiBase extends Resource implements IGraphqlApi {
});
}

/**
* add a new OpenSearch data source to this API
*
* @param id The data source's id
* @param domain The OpenSearch domain for this data source
* @param options The optional configuration for this data source
*/
public addOpenSearchDataSource(id: string, domain: IOpenSearchDomain, options?: DataSourceOptions): OpenSearchDataSource {
return new OpenSearchDataSource(this, id, {
api: this,
name: options?.name,
description: options?.description,
domain,
});
}

/**
* creates a new resolver for this datasource and API using the given properties
*/
Expand All @@ -273,4 +301,4 @@ export abstract class GraphqlApiBase extends Resource implements IGraphqlApi {
construct;
return false;
}
}
}
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-appsync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"@aws-cdk/aws-elasticsearch": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-opensearchservice": "0.0.0",
"@aws-cdk/aws-rds": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/aws-secretsmanager": "0.0.0",
Expand All @@ -109,6 +110,7 @@
"@aws-cdk/aws-elasticsearch": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-opensearchservice": "0.0.0",
"@aws-cdk/aws-rds": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/aws-secretsmanager": "0.0.0",
Expand Down
17 changes: 9 additions & 8 deletions packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as path from 'path';
import { Template } from '@aws-cdk/assertions';
import * as es from '@aws-cdk/aws-elasticsearch';
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
import * as cdk from '@aws-cdk/core';
import * as appsync from '../lib';

Expand All @@ -20,7 +21,7 @@ beforeEach(() => {
});

describe('Elasticsearch Data Source Configuration', () => {
test('Elasticsearch configure properly', () => {
testDeprecated('Elasticsearch configure properly', () => {
// WHEN
api.addElasticsearchDataSource('ds', domain);

Expand Down Expand Up @@ -51,7 +52,7 @@ describe('Elasticsearch Data Source Configuration', () => {
});
});

test('Elastic search configuration contains fully qualified url', () => {
testDeprecated('Elastic search configuration contains fully qualified url', () => {
// WHEN
api.addElasticsearchDataSource('ds', domain);

Expand All @@ -67,7 +68,7 @@ describe('Elasticsearch Data Source Configuration', () => {
});
});

test('default configuration produces name identical to the id', () => {
testDeprecated('default configuration produces name identical to the id', () => {
// WHEN
api.addElasticsearchDataSource('ds', domain);

Expand All @@ -78,7 +79,7 @@ describe('Elasticsearch Data Source Configuration', () => {
});
});

test('appsync configures name correctly', () => {
testDeprecated('appsync configures name correctly', () => {
// WHEN
api.addElasticsearchDataSource('ds', domain, {
name: 'custom',
Expand All @@ -91,7 +92,7 @@ describe('Elasticsearch Data Source Configuration', () => {
});
});

test('appsync configures name and description correctly', () => {
testDeprecated('appsync configures name and description correctly', () => {
// WHEN
api.addElasticsearchDataSource('ds', domain, {
name: 'custom',
Expand All @@ -106,7 +107,7 @@ describe('Elasticsearch Data Source Configuration', () => {
});
});

test('appsync errors when creating multiple elasticsearch data sources with no configuration', () => {
testDeprecated('appsync errors when creating multiple elasticsearch data sources with no configuration', () => {
// WHEN
const when = () => {
api.addElasticsearchDataSource('ds', domain);
Expand All @@ -119,7 +120,7 @@ describe('Elasticsearch Data Source Configuration', () => {
});

describe('adding elasticsearch data source from imported api', () => {
test('imported api can add ElasticsearchDataSource from id', () => {
testDeprecated('imported api can add ElasticsearchDataSource from id', () => {
// WHEN
const importedApi = appsync.GraphqlApi.fromGraphqlApiAttributes(stack, 'importedApi', {
graphqlApiId: api.apiId,
Expand All @@ -133,7 +134,7 @@ describe('adding elasticsearch data source from imported api', () => {
});
});

test('imported api can add ElasticsearchDataSource from attributes', () => {
testDeprecated('imported api can add ElasticsearchDataSource from attributes', () => {
// WHEN
const importedApi = appsync.GraphqlApi.fromGraphqlApiAttributes(stack, 'importedApi', {
graphqlApiId: api.apiId,
Expand Down
Loading

0 comments on commit 922a9dc

Please sign in to comment.