From 5c7fd9827defb381acdfe701981e984b1d0aa928 Mon Sep 17 00:00:00 2001 From: j3tto <james@stackcrafters.com> Date: Mon, 14 Dec 2020 18:31:49 +0000 Subject: [PATCH 1/2] Added option for defining `timeToLiveSpecification` as part of table definition --- README.md | 3 +++ src/serverless.js | 8 +++++++- src/utils.js | 15 +++++++++++++++ test/integration.test.js | 8 +++++++- test/utils.js | 23 +++++++++++++++++++++-- 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7d07fe2..7746814 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,9 @@ inputs: KeyType: HASH Projection: ProjectionType: 'ALL' + timeToLiveSpecification: # (optional) + AttributeName: attribute2 + Enabled: false region: us-east-1 ``` diff --git a/src/serverless.js b/src/serverless.js index 8c34659..4c2891f 100644 --- a/src/serverless.js +++ b/src/serverless.js @@ -5,7 +5,7 @@ const { mergeDeepRight, pick } = require('ramda'); const AWS = require('aws-sdk'); // eslint-disable-next-line import/no-unresolved const { Component } = require('@serverless/core'); -const { log, createTable, deleteTable, describeTable, updateTable } = require('./utils'); +const { log, createTable, deleteTable, describeTable, updateTable, updateTimeToLive } = require('./utils'); const outputsList = ['name', 'arn', 'region']; @@ -27,6 +27,7 @@ const defaults = { name: null, region: 'us-east-1', deletionPolicy: 'delete', + timeToLiveSpecification: undefined }; class AwsDynamoDb extends Component { @@ -88,6 +89,11 @@ class AwsDynamoDb extends Component { await updateTable.call(this, { dynamodb, prevGlobalSecondaryIndexes, ...config }); } + if (config.timeToLiveSpecification) { + await updateTimeToLive({dynamodb, ...config}) + + } + log(`Table ${config.name} was successfully deployed to the ${config.region} region.`); this.state.arn = config.arn; diff --git a/src/utils.js b/src/utils.js index 7ae0545..d7e7abe 100644 --- a/src/utils.js +++ b/src/utils.js @@ -119,10 +119,25 @@ async function deleteTable({ dynamodb, name }) { return !!res; } +async function updateTimeToLive({dynamodb, name, timeToLiveSpecification= {}}) { + return await dynamodb.waitFor('tableExists', { TableName: name}, async function(err, data) { + if (err) throw err; + return await dynamodb + .updateTimeToLive({ + TableName: name, + TimeToLiveSpecification: { + AttributeName: timeToLiveSpecification.AttributeName, + Enabled: timeToLiveSpecification.Enabled, + } + }).promise(); + }).promise(); +} + module.exports = { log, createTable, describeTable, updateTable, deleteTable, + updateTimeToLive, }; diff --git a/test/integration.test.js b/test/integration.test.js index 5e402b1..8775c79 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -1,6 +1,6 @@ 'use strict'; -const { sleep, generateId, getCredentials, getServerlessSdk, getTable } = require('./utils'); +const { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive } = require('./utils'); // set enough timeout for deployment to finish jest.setTimeout(30000); @@ -16,6 +16,10 @@ const instanceYaml = { stage: 'dev', inputs: { deletionPolicy: 'delete', + timeToLiveSpecification: { + AttributeName : 'expires', + Enabled: true + }, attributeDefinitions: [ { AttributeName: 'attribute1', @@ -75,6 +79,8 @@ it('should successfully deploy dynamodb table and local index', async () => { const res = await getTable(credentials, name); + //const resTTL = await getTableTimeToLive(credentials, name); + expect(instance.outputs.name).toBeDefined(); expect(instance.outputs.arn).toBeDefined(); expect(res.Table.AttributeDefinitions.length).toEqual(2); diff --git a/test/utils.js b/test/utils.js index 183fae3..3849ef5 100644 --- a/test/utils.js +++ b/test/utils.js @@ -28,7 +28,7 @@ const getCredentials = () => { }; if (!credentials.aws.accessKeyId || !credentials.aws.accessKeyId) { - throw new Error('Unable to run tests. AWS credentials not found in the envionrment'); + throw new Error('Unable to run tests. AWS credentials not found in the environment'); } return credentials; @@ -67,4 +67,23 @@ const getTable = async (credentials, tableName) => { .promise(); }; -module.exports = { sleep, generateId, getCredentials, getServerlessSdk, getTable }; +/* + * Fetches a DynamoDB timeToLive for a table from aws for validation + * @param ${object} credentials - the cross provider credentials object + * @param ${string} tableName - the name of the dynamodb table + */ +const getTableTimeToLive = async (credentials, tableName) => { + const config = { + credentials: credentials.aws, + region: 'us-east-1', + }; + const dynamodb = new AWS.DynamoDB(config); + + return dynamodb + .describeTimeToLive({ + TableName: tableName, + }) + .promise(); +}; + +module.exports = { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive }; From 6deda45f6281bd54bc858785fdcda1bc9b4c20c9 Mon Sep 17 00:00:00 2001 From: j3tto <james@stackcrafters.com> Date: Mon, 14 Dec 2020 18:43:24 +0000 Subject: [PATCH 2/2] Fix Lint Errors --- src/serverless.js | 14 +++++++--- src/utils.js | 27 ++++++++++--------- .../serverless.template.yml | 2 +- test/integration.test.js | 8 +++--- test/utils.js | 9 ++++++- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/serverless.js b/src/serverless.js index 4c2891f..484fe65 100644 --- a/src/serverless.js +++ b/src/serverless.js @@ -5,7 +5,14 @@ const { mergeDeepRight, pick } = require('ramda'); const AWS = require('aws-sdk'); // eslint-disable-next-line import/no-unresolved const { Component } = require('@serverless/core'); -const { log, createTable, deleteTable, describeTable, updateTable, updateTimeToLive } = require('./utils'); +const { + log, + createTable, + deleteTable, + describeTable, + updateTable, + updateTimeToLive, +} = require('./utils'); const outputsList = ['name', 'arn', 'region']; @@ -27,7 +34,7 @@ const defaults = { name: null, region: 'us-east-1', deletionPolicy: 'delete', - timeToLiveSpecification: undefined + timeToLiveSpecification: undefined, }; class AwsDynamoDb extends Component { @@ -90,8 +97,7 @@ class AwsDynamoDb extends Component { } if (config.timeToLiveSpecification) { - await updateTimeToLive({dynamodb, ...config}) - + await updateTimeToLive({ dynamodb, ...config }); } log(`Table ${config.name} was successfully deployed to the ${config.region} region.`); diff --git a/src/utils.js b/src/utils.js index d7e7abe..2023fc0 100644 --- a/src/utils.js +++ b/src/utils.js @@ -119,18 +119,21 @@ async function deleteTable({ dynamodb, name }) { return !!res; } -async function updateTimeToLive({dynamodb, name, timeToLiveSpecification= {}}) { - return await dynamodb.waitFor('tableExists', { TableName: name}, async function(err, data) { - if (err) throw err; - return await dynamodb - .updateTimeToLive({ - TableName: name, - TimeToLiveSpecification: { - AttributeName: timeToLiveSpecification.AttributeName, - Enabled: timeToLiveSpecification.Enabled, - } - }).promise(); - }).promise(); +async function updateTimeToLive({ dynamodb, name, timeToLiveSpecification = {} }) { + return await dynamodb + .waitFor('tableExists', { TableName: name }, async (err) => { + if (err) throw err; + return await dynamodb + .updateTimeToLive({ + TableName: name, + TimeToLiveSpecification: { + AttributeName: timeToLiveSpecification.AttributeName, + Enabled: timeToLiveSpecification.Enabled, + }, + }) + .promise(); + }) + .promise(); } module.exports = { diff --git a/templates/aws-dynamodb-starter/serverless.template.yml b/templates/aws-dynamodb-starter/serverless.template.yml index 509d303..93488a4 100644 --- a/templates/aws-dynamodb-starter/serverless.template.yml +++ b/templates/aws-dynamodb-starter/serverless.template.yml @@ -3,4 +3,4 @@ org: serverlessinc description: Deploys a serverless NoSQL database powered by AWS DynamoDB keywords: aws, serverless, nosql, database repo: https://github.com/serverless-components/aws-dynamodb -license: MIT \ No newline at end of file +license: MIT diff --git a/test/integration.test.js b/test/integration.test.js index 8775c79..2756d59 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -1,6 +1,6 @@ 'use strict'; -const { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive } = require('./utils'); +const { sleep, generateId, getCredentials, getServerlessSdk, getTable } = require('./utils'); // set enough timeout for deployment to finish jest.setTimeout(30000); @@ -17,8 +17,8 @@ const instanceYaml = { inputs: { deletionPolicy: 'delete', timeToLiveSpecification: { - AttributeName : 'expires', - Enabled: true + AttributeName: 'expires', + Enabled: true, }, attributeDefinitions: [ { @@ -79,7 +79,7 @@ it('should successfully deploy dynamodb table and local index', async () => { const res = await getTable(credentials, name); - //const resTTL = await getTableTimeToLive(credentials, name); + // const resTTL = await getTableTimeToLive(credentials, name); expect(instance.outputs.name).toBeDefined(); expect(instance.outputs.arn).toBeDefined(); diff --git a/test/utils.js b/test/utils.js index 3849ef5..5e47786 100644 --- a/test/utils.js +++ b/test/utils.js @@ -86,4 +86,11 @@ const getTableTimeToLive = async (credentials, tableName) => { .promise(); }; -module.exports = { sleep, generateId, getCredentials, getServerlessSdk, getTable, getTableTimeToLive }; +module.exports = { + sleep, + generateId, + getCredentials, + getServerlessSdk, + getTable, + getTableTimeToLive, +};