Skip to content

Commit

Permalink
fix(amplify-category-analytics): delete pinpoint project in delete (#…
Browse files Browse the repository at this point in the history
…3165)

* fix(amplify-category-analytics): delete pinpoint project in delete

fix #2974

* test(amplify-e2e-tests): add e2e test for pinpoint project delete

* update for changed analytics prompt

* typo correction

Co-authored-by: Zhou <zhoweimi@186590ce137f.ant.amazon.com>
  • Loading branch information
UnleashedMind and Zhou committed Mar 9, 2020
1 parent 051b2fb commit acc0240
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"roleName": {
"Type": "String"
},
"cloudformationPolicyName": {
"Type": "String"
},
"cloudWatchPolicyName": {
"Type": "String"
},
Expand Down Expand Up @@ -136,6 +139,21 @@
}
]
}
},
{
"PolicyName": {
"Ref": "cloudformationPolicyName"
},
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["cloudformation:*"],
"Resource": "*"
}
]
}
}
]
}
Expand All @@ -153,8 +171,33 @@
"const aws = require('aws-sdk');",
"exports.handler = function(event, context) {",
" if (event.RequestType == 'Delete') {",
" response.send(event, context, response.SUCCESS);",
" return;",
" const stackID = event.StackId;",
" const cloudFormationClient = new aws.CloudFormation({ apiVersion: '2016-12-01', region: event.ResourceProperties.region });",
" cloudFormationClient.describeStacks({ StackName: stackID }).promise()",
" .then(describeStacksOutput => {",
" let appId;",
" if (describeStacksOutput.Stacks && describeStacksOutput.Stacks.length > 0) {",
" const { Outputs } = describeStacksOutput.Stacks[0];",
" const appIdOutput = Outputs.find((output)=>{ return output.OutputKey === 'Id'});",
" appId = appIdOutput ? appIdOutput.OutputValue : undefined; ",
" }",
" return appId;",
" })",
" .then(appId => {",
" if (appId) {",
" const pinpointClient = new aws.Pinpoint({ apiVersion: '2016-12-01', region: event.ResourceProperties.pingPointRegion });",
" const params = {",
" ApplicationId: appId,",
" };",
" pinpointClient.deleteApp(params).promise();",
" }",
" })",
" .then(()=>{",
" response.send(event, context, response.SUCCESS, {'message': `Successfully deleted pinpoint project`});",
" })",
" .catch(e=>{",
" response.send(event, context, response.FAILED, {'message': `Failed to deleted Pinpoint project`, 'exception': e});",
" }); ",
" }",
" if (event.RequestType == 'Update') {",
" response.send(event, context, response.SUCCESS);",
Expand All @@ -168,7 +211,7 @@
" Name: appName",
" }",
" };",
" const pinpoint = new aws.Pinpoint({ apiVersion: '2016-12-01', region: event.ResourceProperties.region });",
" const pinpoint = new aws.Pinpoint({ apiVersion: '2016-12-01', region: event.ResourceProperties.pingPointRegion });",
" pinpoint.createApp(params).promise()",
" .then((res) => {",
" responseData = res.ApplicationResponse;",
Expand Down Expand Up @@ -201,6 +244,9 @@
"Fn::GetAtt": ["PinpointFunction", "Arn"]
},
"region": {
"Ref": "AWS::Region"
},
"pingPointRegion": {
"Fn::FindInMap": ["RegionMapping", { "Ref": "AWS::Region" }, "pinpointRegion"]
},
"appName": {
Expand All @@ -225,7 +271,8 @@
}
]
}
}
},
"DependsOn": "PinpointFunction"
},
"CognitoUnauthPolicy": {
"Type": "AWS::IAM::Policy",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const getAllDefaults = project => {
appName,
resourceName: appName,
roleName: `pinpointLambdaRole${shortId}`,
cloudformationPolicyName: `cloudformationPolicy${shortId}`,
cloudWatchPolicyName: `cloudWatchPolicy${shortId}`,
pinpointPolicyName: `pinpointPolicy${shortId}`,
authPolicyName: `pinpoint_amplify_${shortId}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async function deletePinpointAppForEnv(context, envName) {
const params = {
ApplicationId: pinpointApp.Id,
};
const pinpointClient = await pinpointHelper.getPinpointClient(context, 'delete');
const pinpointClient = await pinpointHelper.getPinpointClient(context, 'delete', envName);

return pinpointClient
.deleteApp(params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ function console(context) {
}
}

async function getPinpointClient(context, action) {
async function getPinpointClient(context, action, envName) {
const providerPlugins = context.amplify.getProviderPlugins(context);
const provider = require(providerPlugins[providerName]);
return provider.getConfiguredPinpointClient(context, constants.CategoryName, action);
return provider.getConfiguredPinpointClient(context, constants.CategoryName, action, envName);
}

function isAnalyticsAdded(context) {
Expand Down
7 changes: 6 additions & 1 deletion packages/amplify-e2e-tests/sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ GOOGLE_APP_ID=<your-google-app-id>
GOOGLE_APP_SECRET=<your-google-app-secret>

AMAZON_APP_ID=<your-amazon-app-id>
AMAZON_APP_SECRET=<your-amazon-app-secret>
AMAZON_APP_SECRET=<your-amazon-app-secret>

#Used for delete test
AWS_ACCESS_KEY_ID=<your-access-key>
AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
CLI_REGION=<region>
14 changes: 14 additions & 0 deletions packages/amplify-e2e-tests/src/__tests__/delete.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { addEnvironment, checkoutEnvironment, removeEnvironment } from '../envir
import { addApiWithoutSchema } from '../categories/api';
import { addCodegen } from '../codegen/add';
import * as fs from 'fs-extra';
import * as pinpointHelper from '../utils/pinpoint';

describe('amplify delete', () => {
let projRoot: string;
Expand All @@ -40,6 +41,19 @@ describe('amplify delete', () => {
await testDeletion(projRoot, { android: true });
});

it('should delete pinpoint project', async () => {
await pinpointHelper.initProject(projRoot, true);
const pinpointResourceName = await pinpointHelper.addPinpointAnalytics(projRoot, true);
await pinpointHelper.pushToCloud(projRoot, true);
const amplifyMeta = getProjectMeta(projRoot);
const pintpointAppId = amplifyMeta.analytics[pinpointResourceName].output.Id;
let pinpointAppExists = await pinpointHelper.pinpointAppExist(pintpointAppId);
expect(pinpointAppExists).toBeTruthy();
await pinpointHelper.amplifyDelete(projRoot, true);
pinpointAppExists = await pinpointHelper.pinpointAppExist(pintpointAppId);
expect(pinpointAppExists).toBeFalsy();
});

it('should remove enviroment', async () => {
await initJSProjectWithProfile(projRoot, { envName: 'testdev' });
await addEnvironment(projRoot, { envName: 'testprod' });
Expand Down
146 changes: 146 additions & 0 deletions packages/amplify-e2e-tests/src/utils/pinpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { nspawn as spawn } from '../utils/nexpect';
import { getCLIPath, isCI } from '../utils';
import { Pinpoint } from 'aws-sdk';

const settings = {
name: '\r',
envName: 'test',
editor: '\r',
appType: '\r',
framework: '\r',
srcDir: '\r',
distDir: '\r',
buildCmd: '\r',
startCmd: '\r',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.CLI_REGION,
pinpointResourceName: 'testpinpoint',
};

export async function pinpointAppExist(pinpointProjectId: string): Promise<boolean> {
let result = false;

const pinpointClient = new Pinpoint({
accessKeyId: settings.accessKeyId,
secretAccessKey: settings.secretAccessKey,
region: settings.region,
});

try {
const response = await pinpointClient
.getApp({
ApplicationId: pinpointProjectId,
})
.promise();
if (response.ApplicationResponse.Id === pinpointProjectId) {
result = true;
}
} catch (err) {
if (err.code === 'NotFoundException') {
result = false;
} else {
throw err;
}
}

return result;
}

export function initProject(cwd: string, verbose: boolean = !isCI()) {
return new Promise((resolve, reject) => {
spawn(getCLIPath(), ['init'], { cwd, stripColors: true, verbose })
.wait('Enter a name for the project')
.sendLine(settings.name)
.wait('Enter a name for the environment')
.sendLine(settings.envName)
.wait('Choose your default editor:')
.sendLine(settings.editor)
.wait("Choose the type of app that you're building")
.sendLine(settings.appType)
.wait('What javascript framework are you using')
.sendLine(settings.framework)
.wait('Source Directory Path:')
.sendLine(settings.srcDir)
.wait('Distribution Directory Path:')
.sendLine(settings.distDir)
.wait('Build Command:')
.sendLine(settings.buildCmd)
.wait('Start Command:')
.sendLine(settings.startCmd)
.wait('Using default provider awscloudformation')
.wait('Do you want to use an AWS profile?')
.sendLine('n')
.pauseRecording()
.wait('accessKeyId')
.sendLine(settings.accessKeyId)
.wait('secretAccessKey')
.sendLine(settings.secretAccessKey)
.resumeRecording()
.wait('region')
.sendLine(settings.region)
.wait('Try "amplify add api" to create a backend API and then "amplify publish" to deploy everything')
.run((err: Error) => {
if (!err) {
resolve();
} else {
reject(err);
}
});
});
}

export function addPinpointAnalytics(cwd: string, verbose: boolean = !isCI()): Promise<string> {
return new Promise((resolve, reject) => {
spawn(getCLIPath(), ['add', 'analytics'], { cwd, stripColors: true, verbose })
.wait('Please select from one of the below mentioned services')
.sendCarriageReturn()
.wait('Provide your pinpoint resource name:')
.sendLine(settings.pinpointResourceName)
.wait('Apps need authorization to send analytics events. Do you want to allow guests')
.sendLine('n')
.wait(`Successfully added resource ${settings.pinpointResourceName} locally`)
.sendEof()
.run((err: Error) => {
if (!err) {
resolve(settings.pinpointResourceName);
} else {
reject(err);
}
});
});
}

export function pushToCloud(cwd: string, verbose: boolean = !isCI()) {
return new Promise((resolve, reject) => {
spawn(getCLIPath(), ['push'], { cwd, stripColors: true, verbose })
.wait('Are you sure you want to continue')
.sendCarriageReturn()
.wait('All resources are updated in the cloud')
.wait('Pinpoint URL to track events')
.run((err: Error) => {
if (!err) {
resolve();
} else {
reject(err);
}
});
});
}

export function amplifyDelete(cwd: string, verbose: boolean = !isCI()) {
return new Promise((resolve, reject) => {
spawn(getCLIPath(), ['delete'], { cwd, stripColors: true, verbose })
.wait('Are you sure you want to continue?')
.sendLine('Y')
.wait('Project deleted in the cloud')
.wait('Project deleted locally.')
.run((err: Error) => {
if (!err) {
resolve();
} else {
reject(err);
}
});
});
}
4 changes: 2 additions & 2 deletions packages/amplify-provider-awscloudformation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ async function getConfiguredAWSClient(context, category, action) {
return aws;
}

function getConfiguredPinpointClient(context, category, action, options = {}) {
return pinpoint.getConfiguredPinpointClient(context, category, action, options);
function getConfiguredPinpointClient(context, category, action, envName) {
return pinpoint.getConfiguredPinpointClient(context, category, action, envName);
}

function getPinpointRegionMapping() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ const serviceRegionMap = {
'eu-west-3': 'eu-west-1',
};

async function getConfiguredPinpointClient(context, category, action, options = {}) {
async function getConfiguredPinpointClient(context, category, action, envName) {
let cred = {};
const httpProxy = process.env.HTTP_PROXY || process.env.HTTPS_PROXY;

try {
cred = await configurationManager.loadConfiguration(context);
if (envName) {
cred = await configurationManager.loadConfigurationForEnv(context, envName);
} else {
cred = await configurationManager.loadConfiguration(context);
}
} catch (e) {
// ignore missing config
}
Expand All @@ -50,7 +54,7 @@ async function getConfiguredPinpointClient(context, category, action, options =
});
}

return new aws.Pinpoint({ ...cred, ...defaultOptions, ...options });
return new aws.Pinpoint({ ...cred, ...defaultOptions });
}

function mapServiceRegion(region) {
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3793,6 +3793,16 @@ amdefine@>=0.0.4:
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=

amplify-frontend-javascript@2.13.2:
version "2.13.2"
resolved "https://registry.yarnpkg.com/amplify-frontend-javascript/-/amplify-frontend-javascript-2.13.2.tgz#c97c6e1e792b08a84a9ab6be5333c54379f2eeaf"
integrity sha512-VbvqN6gVTPXKWKLGuCCitCy6QF3i8dPsUDvKwIouJvxjk/RnBqaHbQCv25RBza+l29y2cV7w5HuF7KwLOHa+Zg==
dependencies:
chalk "^3.0.0"
fs-extra "^8.1.0"
graphql-config "^2.2.1"
inquirer "^7.0.3"

ansi-colors@3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
Expand Down

0 comments on commit acc0240

Please sign in to comment.