Skip to content

Commit

Permalink
feat: migration of hosting and notifications (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
UnleashedMind authored and kaustavghosh06 committed Nov 28, 2018
1 parent 832ad48 commit f6a60b6
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 49 deletions.
2 changes: 1 addition & 1 deletion packages/amplify-category-hosting/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async function console(context) {
}

async function migrate(context) {
context.print.info('hosting migrate...');
await categoryManager.migrate(context);
}

module.exports = {
Expand Down
67 changes: 67 additions & 0 deletions packages/amplify-category-hosting/lib/S3AndCloudFront/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,76 @@ function console(context) {
opn(consoleUrl, { wait: false });
}

async function migrate(context) {
const projectBackendDirPath = context.amplify.pathManager.getBackendDirPath();
const serviceDirPath = path.join(projectBackendDirPath, constants.CategoryName, serviceName);
if (fs.existsSync(serviceDirPath)) {
const templateFilePath = path.join(serviceDirPath, templateFileName);
if (fs.existsSync(templateFilePath)) {
let template = JSON.parse(fs.readFileSync(templateFilePath));
let parameters;
const parametersFilePath = path.join(serviceDirPath, parametersFileName);
if (fs.existsSync(parametersFilePath)) {
parameters = JSON.parse(fs.readFileSync(parametersFilePath));
}

const migrationInfo = extractMigrationInfo(template);

template = migrateTemplate(template, migrationInfo);
parameters = migrateParameters(parameters, migrationInfo);

let jsonString = JSON.stringify(template, null, 4);
fs.writeFileSync(templateFilePath, jsonString, 'utf8');

jsonString = JSON.stringify(parameters, null, 4);
fs.writeFileSync(parametersFilePath, jsonString, 'utf8');
}
}
}

function extractMigrationInfo(template) {
const migrationInfo = {};
if (template.Resources.S3Bucket) {
if ((typeof template.Resources.S3Bucket.Properties.BucketName) === 'string') {
migrationInfo.BucketName = template.Resources.S3Bucket.Properties.BucketName;
}
}
return migrationInfo;
}

function migrateTemplate(template, migrationInfo) {
const templateFilePath = path.join(__dirname, templateFileName);
const templateNewVersion = JSON.parse(fs.readFileSync(templateFilePath));

template.Parameters = template.Parameters || {};
Object.assign(template.Parameters, templateNewVersion.Parameters);

template.Conditions = template.Conditions || {};
Object.assign(template.Conditions, templateNewVersion.Conditions);

if (migrationInfo.BucketName) {
template.Resources.S3Bucket.Properties.BucketName =
templateNewVersion.Resources.S3Bucket.Properties.BucketName;
}

return template;
}

function migrateParameters(parameters, migrationInfo) {
parameters = parameters || {};
if (migrationInfo.BucketName) {
const parametersFilePath = path.join(__dirname, parametersFileName);
const parametersNewVersion = JSON.parse(fs.readFileSync(parametersFilePath));
parametersNewVersion.bucketName = migrationInfo.BucketName;
Object.assign(parameters, parametersNewVersion);
}
return parameters;
}

module.exports = {
enable,
configure,
publish,
console,
migrate,
};
15 changes: 15 additions & 0 deletions packages/amplify-category-hosting/lib/category-manager.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const fs = require('fs-extra');
const path = require('path');
const sequential = require('promise-sequential');
const constants = require('./constants');
const supportedServices = require('./supported-services');

Expand Down Expand Up @@ -60,7 +61,21 @@ function runServiceAction(context, service, action, args) {
return serviceModule[action](context, args);
}

async function migrate(context) {
const migrationTasks = [];
const { migrationInfo } = context;
const categoryMeta = migrationInfo.amplifyMeta[constants.CategoryName];
if (categoryMeta) {
Object.keys(categoryMeta).forEach((service) => {
const serviceModule = require(path.join(__dirname, `${service}/index.js`));
migrationTasks.push(() => serviceModule.migrate(context));
});
}
await sequential(migrationTasks);
}

module.exports = {
getCategoryStatus,
runServiceAction,
migrate,
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,50 +11,55 @@ module.exports = {
alias: ['disable', 'delete'],
run: async (context) => {
context.exeInfo = context.amplify.getProjectDetails();
const availableChannels = notificationManager.getAvailableChannels(context);
const enabledChannels = notificationManager.getEnabledChannels(context);
const pinpointApp = pinpointHelper.getPinpointApp(context);
if (pinpointApp) {
const availableChannels = notificationManager.getAvailableChannels(context);
const enabledChannels = notificationManager.getEnabledChannels(context);

enabledChannels.push(PinpointApp);
enabledChannels.push(Cancel);
enabledChannels.push(PinpointApp);
enabledChannels.push(Cancel);

let channelName = context.parameters.first;
let channelName = context.parameters.first;

if (!channelName || !availableChannels.includes(channelName)) {
const answer = await inquirer.prompt({
name: 'selection',
type: 'list',
message: 'Choose what to remove.',
choices: enabledChannels,
default: enabledChannels[0],
});
channelName = answer.selection;
} else if (!enabledChannels.includes(channelName)) {
context.print.info(`The ${channelName} channel has NOT been enabled.`);
channelName = undefined;
}

if (channelName && channelName !== Cancel) {
if (channelName !== PinpointApp) {
await pinpointHelper.ensurePinpointApp(context);
await notificationManager.disableChannel(context, channelName);
multiEnvManager.writeData(context);
} else if (pinpointHelper.isAnalyticsAdded(context)) {
context.print.error('Execution aborted.');
context.print.info('You have an analytics resource in your backend tied to the Amazon Pinpoint resource');
context.print.info('The Analytics resource must be removed before Amazon Pinpoint can be deleted from the cloud');
} else {
if (!channelName || !availableChannels.includes(channelName)) {
const answer = await inquirer.prompt({
name: 'deletePinpointApp',
type: 'confirm',
message: 'Confirm that you want to delete the associated Amazon Pinpoint application',
default: false,
name: 'selection',
type: 'list',
message: 'Choose what to remove.',
choices: enabledChannels,
default: enabledChannels[0],
});
if (answer.deletePinpointApp) {
await pinpointHelper.deletePinpointApp(context);
context.print.info('The Pinpoint application has been successfully deleted.');
channelName = answer.selection;
} else if (!enabledChannels.includes(channelName)) {
context.print.info(`The ${channelName} channel has NOT been enabled.`);
channelName = undefined;
}

if (channelName && channelName !== Cancel) {
if (channelName !== PinpointApp) {
await pinpointHelper.ensurePinpointApp(context);
await notificationManager.disableChannel(context, channelName);
multiEnvManager.writeData(context);
} else if (pinpointHelper.isAnalyticsAdded(context)) {
context.print.error('Execution aborted.');
context.print.info('You have an analytics resource in your backend tied to the Amazon Pinpoint resource');
context.print.info('The Analytics resource must be removed before Amazon Pinpoint can be deleted from the cloud');
} else {
const answer = await inquirer.prompt({
name: 'deletePinpointApp',
type: 'confirm',
message: 'Confirm that you want to delete the associated Amazon Pinpoint application',
default: false,
});
if (answer.deletePinpointApp) {
await pinpointHelper.deletePinpointApp(context);
context.print.info('The Pinpoint application has been successfully deleted.');
multiEnvManager.writeData(context);
}
}
}
} else {
context.print.error('Notifications have not been added to your project.');
}
return context;
},
Expand Down
2 changes: 1 addition & 1 deletion packages/amplify-category-notifications/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ async function initEnvPush(context) {
}

async function migrate(context) {
context.print.info('notifications migrate...');
await multiEnvManager.migrate(context);
}

module.exports = {
Expand Down
77 changes: 77 additions & 0 deletions packages/amplify-category-notifications/lib/multi-env-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,87 @@ function writeAmplifyMeta(categoryMeta, amplifyMetaFilePath) {
}
}

async function migrate(context) {
const migrationInfo = extractMigrationInfo(context);
fillBackendConfig(context, migrationInfo);
fillTeamProviderInfo(context, migrationInfo);
}

function extractMigrationInfo(context) {
let migrationInfo;
const { amplifyMeta, localEnvInfo } = context.migrationInfo;
if (amplifyMeta[constants.CategoryName]) {
const categoryMeta = amplifyMeta[constants.CategoryName];
const services = Object.keys(categoryMeta);
for (let i = 0; i < services.length; i++) {
const service = services[i];
const serviceMeta = amplifyMeta[constants.CategoryName][service];
if (serviceMeta.service === constants.PinpointName) {
migrationInfo = {};
migrationInfo.envName = localEnvInfo.envName;
migrationInfo.serviceName = service;
migrationInfo.service = serviceMeta.service;
migrationInfo.output = serviceMeta.output;
break;
}
}
}

if (migrationInfo &&
migrationInfo.output &&
migrationInfo.output.Id) {
migrationInfo.Id = migrationInfo.output.Id;
migrationInfo.Name = migrationInfo.output.Name;
migrationInfo.Region = migrationInfo.output.Region;
migrationInfo.channels = [];
const availableChannels = notificationManager.getAvailableChannels();
availableChannels.forEach((channel) => {
if (migrationInfo.output[channel] && migrationInfo.output[channel].Enabled) {
migrationInfo.channels.push(channel);
}
});
}

return migrationInfo;
}

function fillBackendConfig(context, migrationInfo) {
if (migrationInfo) {
const backendConfig = {};
backendConfig[migrationInfo.serviceName] = {
service: migrationInfo.service,
channels: migrationInfo.channels,
};
Object.assign(context.migrationInfo.backendConfig[constants.CategoryName], backendConfig);
}
}

function fillTeamProviderInfo(context, migrationInfo) {
if (migrationInfo && migrationInfo.Id) {
const categoryTeamInfo = {};
categoryTeamInfo[constants.CategoryName] = {};
categoryTeamInfo[constants.CategoryName][constants.PinpointName] = {
Name: migrationInfo.Name,
Id: migrationInfo.Id,
Region: migrationInfo.Region,
};

const { teamProviderInfo } = context.migrationInfo;
teamProviderInfo[migrationInfo.envName] =
teamProviderInfo[migrationInfo.envName] || {};

teamProviderInfo[migrationInfo.envName].categories =
teamProviderInfo[migrationInfo.envName].categories || {};

Object.assign(teamProviderInfo[migrationInfo.envName].categories, categoryTeamInfo);
}
}

module.exports = {
initEnv,
initEnvPush,
deletePinpointAppForEnv,
writeData,
migrate,
};

17 changes: 13 additions & 4 deletions packages/amplify-category-notifications/lib/pinpoint-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ const authHelper = require('./auth-helper');
const providerName = 'awscloudformation';
const spinner = ora('');

function getPinpointApp(context) {
const { amplifyMeta } = context.exeInfo;
let pinpointApp = scanCategoryMetaForPinpoint(amplifyMeta[constants.CategoryName]);
if (!pinpointApp) {
pinpointApp = scanCategoryMetaForPinpoint(amplifyMeta[constants.AnalyticsCategoryName]);
}
return pinpointApp;
}

async function ensurePinpointApp(context) {
const { amplifyMeta } = context.exeInfo;
let pinpointApp = scanCategoryMetaForPinpoint(amplifyMeta[constants.CategoryName]);
Expand All @@ -32,7 +41,8 @@ async function ensurePinpointApp(context) {
}
}
context.exeInfo.pinpointApp = pinpointApp;
context.exeInfo.serviceMeta = amplifyMeta[constants.CategoryName][pinpointApp.Name];
context.exeInfo.serviceMeta =
context.exeInfo.amplifyMeta[constants.CategoryName][pinpointApp.Name];
}

async function createPinpointApp(context) {
Expand Down Expand Up @@ -102,7 +112,7 @@ function scanCategoryMetaForPinpoint(categoryMeta) {
const services = Object.keys(categoryMeta);
for (let i = 0; i < services.length; i++) {
const serviceMeta = categoryMeta[services[i]];
if (serviceMeta.service === 'Pinpoint' &&
if (serviceMeta.service === constants.PinpointName &&
serviceMeta.output &&
serviceMeta.output.Id) {
result = {
Expand All @@ -113,11 +123,9 @@ function scanCategoryMetaForPinpoint(categoryMeta) {
} else if (serviceMeta.output.appName) {
result.Name = serviceMeta.output.appName;
}

if (serviceMeta.output.Region) {
result.Region = serviceMeta.output.Region;
}

break;
}
}
Expand Down Expand Up @@ -235,6 +243,7 @@ function isAnalyticsAdded(context) {
}

module.exports = {
getPinpointApp,
ensurePinpointApp,
deletePinpointApp,
getPinpointClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ const amplifyCLIConstants = require('./constants.js');
function projectPathValidate(projectPath) {
let isGood = false;
if (fs.existsSync(projectPath)) {
const dotamplifyDirPath = getAmplifyDirPath(projectPath);
const amplifyDirPath = getAmplifyDirPath(projectPath);
const infoSubDirPath = getDotConfigDirPath(projectPath);

isGood = fs.existsSync(dotamplifyDirPath) &&
isGood = fs.existsSync(amplifyDirPath) &&
fs.existsSync(infoSubDirPath);
}
return isGood;
Expand Down
8 changes: 3 additions & 5 deletions packages/amplify-cli/src/lib/migrate-project.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ const confirmMigrateMessage =
'We detected the project was initialized using an older version of the CLI. Do you want to migrate the project, so that it is compatible with the latest version of the CLI?';

async function migrateProject(context) {
let projectPath;
try {
projectPath = searchProjectRootPath();
} catch (e) {
const projectPath = searchProjectRootPath();
if (!projectPath) {
// New project, hence not able to find the amplify dir
return;
}
Expand Down Expand Up @@ -115,7 +113,7 @@ function generateMigrationInfo(projectConfig, projectPath) {
migrationInfo.amplifyMeta = getAmplifyMeta(projectPath);
migrationInfo.currentAmplifyMeta = getCurrentAmplifyMeta(projectPath);
migrationInfo.projectConfig = generateNewProjectConfig(projectConfig);
migrationInfo.localEnvInfo = generateLocalEnvInfo(migrationInfo.projectConfig);
migrationInfo.localEnvInfo = generateLocalEnvInfo(projectConfig);
migrationInfo.localAwsInfo = generateLocalAwsInfo(projectPath);
migrationInfo.teamProviderInfo = generateTeamProviderInfo(migrationInfo.amplifyMeta);
migrationInfo.backendConfig = generateBackendConfig(migrationInfo.amplifyMeta);
Expand Down

0 comments on commit f6a60b6

Please sign in to comment.