Skip to content

Commit

Permalink
fix: add support for mobile hub migrated resources (#5407)
Browse files Browse the repository at this point in the history
* fix: add support for mobile hub migrated resources

- support push/pull operations
- support CRUD permission assignment to migrated resources
- block multi-env commands
- block update and remove operations on migrated resources

* fix: sigint test failure

* chore: fix lgtm warning

* fix: add 'add notification' and 'update auth' protection

* chore: fix update unit test
  • Loading branch information
Attila Hajdrik authored Sep 30, 2020
1 parent ec02076 commit 5dfe287
Show file tree
Hide file tree
Showing 29 changed files with 370 additions and 181 deletions.
5 changes: 3 additions & 2 deletions packages/amplify-category-analytics/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ async function getPermissionPolicies(context, resourceOpsMapping) {

Object.keys(resourceOpsMapping).forEach(resourceName => {
try {
const providerController = require(`./provider-utils/${amplifyMeta[category][resourceName].providerPlugin}/index`);
if (providerController) {
const providerName = amplifyMeta[category][resourceName].providerPlugin;
if (providerName) {
const providerController = require(`./provider-utils/${providerName}/index`);
const { policy, attributes } = providerController.getPermissionPolicies(
context,
amplifyMeta[category][resourceName].service,
Expand Down
12 changes: 10 additions & 2 deletions packages/amplify-category-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ export async function initEnv(context) {
* configured an RDS datasource
*/
const backendConfigFilePath = amplify.pathManager.getBackendConfigFilePath();

// If this is a mobile hub migrated project without locally added resources then there is no
// backend config exists yet.
if (!fs.existsSync(backendConfigFilePath)) {
return;
}

const backendConfig = amplify.readJsonFile(backendConfigFilePath);

if (!backendConfig[category]) {
Expand Down Expand Up @@ -146,8 +153,9 @@ export async function getPermissionPolicies(context, resourceOpsMapping) {
await Promise.all(
Object.keys(resourceOpsMapping).map(async resourceName => {
try {
const providerController = require(`./provider-utils/${amplifyMeta[category][resourceName].providerPlugin}/index`);
if (providerController) {
const providerName = amplifyMeta[category][resourceName].providerPlugin;
if (providerName) {
const providerController = require(`./provider-utils/${providerName}/index`);
const { policy, attributes } = await providerController.getPermissionPolicies(
context,
amplifyMeta[category][resourceName].service,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export async function updateWalkthrough(context, defaultValuesFilename) {
const defaultValuesSrc = `${__dirname}/../default-values/${defaultValuesFilename}`;
const { getAllDefaults } = await import(defaultValuesSrc);
const allDefaultValues = getAllDefaults(amplify.getProjectDetails());
const resources = allResources.filter(resource => resource.service === serviceName).map(resource => resource.resourceName);
const resources = allResources
.filter(resource => resource.service === serviceName && !!resource.providerPlugin)
.map(resource => resource.resourceName);

// There can only be one appsync resource
if (resources.length === 0) {
Expand Down
1 change: 1 addition & 0 deletions packages/amplify-category-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"amplify-category-function": "2.25.1",
"amplify-cli-core": "1.3.3",
"amplify-headless-interface": "1.4.0",
"amplify-util-headless-input": "1.3.0",
"aws-sdk": "^2.608.0",
"chalk": "^3.0.0",
"chalk-pipe": "^3.0.0",
Expand Down
11 changes: 11 additions & 0 deletions packages/amplify-category-auth/src/commands/auth/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ module.exports = {

if (!Object.keys(existingAuth).length > 0) {
return context.print.warning('Auth has not yet been added to this project.');
} else {
const services = Object.keys(existingAuth);

for (let i = 0; i < services.length; i++) {
const serviceMeta = existingAuth[services[i]];

if (serviceMeta.service === 'Cognito' && !serviceMeta.providerPlugin) {
context.print.error('Auth is migrated from Mobile Hub and cannot be updated with Amplify CLI.');
return context;
}
}
}

context.print.info('Please note that certain attributes may not be overwritten if you choose to use defaults settings.');
Expand Down
5 changes: 3 additions & 2 deletions packages/amplify-category-auth/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ async function getPermissionPolicies(context, resourceOpsMapping) {

Object.keys(resourceOpsMapping).forEach(resourceName => {
try {
const providerController = require(`./provider-utils/${amplifyMeta[category][resourceName].providerPlugin}/index`);
if (providerController) {
const providerName = amplifyMeta[category][resourceName].providerPlugin;
if (providerName) {
const providerController = require(`./provider-utils/${providerName}/index`);
const { policy, attributes } = providerController.getPermissionPolicies(
context,
amplifyMeta[category][resourceName].service,
Expand Down
3 changes: 2 additions & 1 deletion packages/amplify-category-auth/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"src/__tests__",
],
"references": [
{"path": "../amplify-cli-core"},
{"path": "../amplify-headless-interface"},
{"path": "../amplify-cli-core"}
{"path": "../amplify-util-headless-input"},
]
}
5 changes: 3 additions & 2 deletions packages/amplify-category-function/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ export async function getPermissionPolicies(context, resourceOpsMapping) {

Object.keys(resourceOpsMapping).forEach(resourceName => {
try {
const providerController = require(`./provider-utils/${amplifyMeta[category][resourceName].providerPlugin}/index`);
if (providerController) {
const providerName = amplifyMeta[category][resourceName].providerPlugin;
if (providerName) {
const providerController = require(`./provider-utils/${providerName}/index`);
const { policy, attributes } = providerController.getPermissionPolicies(
context,
amplifyMeta[category][resourceName].service,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ export const askExecRolePermissionsQuestions = async (
if (!getPermissionPolicies) {
context.print.warning(`Policies cannot be added for ${category}/${resourceName}`);
continue;
} else if (
amplifyMeta[category][resourceName].service === 'S3AndCloudFront' &&
!amplifyMeta[category][resourceName].providerPlugin
) {
context.print.warning(`Policies cannot be added for ${category}/${resourceName}, since it is a MobileHub imported resource.`);
continue;
} else {
const crudPermissionQuestion = {
type: 'checkbox',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export async function createWalkthrough(
*/
export async function updateWalkthrough(context, lambdaToUpdate?: string) {
const lambdaFuncResourceNames = ((await context.amplify.getResourceStatus()).allResources as any[])
.filter(resource => resource.service === ServiceName.LambdaFunction)
.filter(resource => resource.service === ServiceName.LambdaFunction && !!resource.providerPlugin)
.map(resource => resource.resourceName);

if (lambdaFuncResourceNames.length === 0) {
Expand Down
4 changes: 2 additions & 2 deletions packages/amplify-category-hosting/commands/hosting/remove.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ async function chooseResource(context, inputResourceName) {
const amplifyMetaFilePath = amplify.pathManager.getAmplifyMetaFilePath();
if (fs.existsSync(amplifyMetaFilePath)) {
const amplifyMeta = amplify.readJsonFile(amplifyMetaFilePath);
if (amplifyMeta[category] && Object.keys(amplifyMeta[category]).length > 0) {
let enabledResources = Object.keys(amplifyMeta[category]);
if (amplifyMeta[category] && Object.keys(amplifyMeta[category]).filter(r => !!amplifyMeta[category][r].providerPlugin).length > 0) {
let enabledResources = Object.keys(amplifyMeta[category]).filter(r => !!amplifyMeta[category][r].providerPlugin);

let inputIsValid = true;
if (services && services.length > 0) {
Expand Down
9 changes: 5 additions & 4 deletions packages/amplify-category-interactions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async function migrate(context) {
const providerController = require(`./provider-utils/${amplifyMeta[category][resourceName].providerPlugin}/index`);
if (providerController) {
migrateResourcePromises.push(
providerController.migrateResource(context, projectPath, amplifyMeta[category][resourceName].service, resourceName)
providerController.migrateResource(context, projectPath, amplifyMeta[category][resourceName].service, resourceName),
);
} else {
context.print.error(`Provider not configured for ${category}: ${resourceName}`);
Expand All @@ -36,13 +36,14 @@ async function getPermissionPolicies(context, resourceOpsMapping) {

Object.keys(resourceOpsMapping).forEach(resourceName => {
try {
const providerController = require(`./provider-utils/${amplifyMeta[category][resourceName].providerPlugin}/index`);
if (providerController) {
const providerName = amplifyMeta[category][resourceName].providerPlugin;
if (providerName) {
const providerController = require(`./provider-utils/${providerName}/index`);
const { policy, attributes } = providerController.getPermissionPolicies(
context,
amplifyMeta[category][resourceName].service,
resourceName,
resourceOpsMapping[resourceName]
resourceOpsMapping[resourceName],
);
permissionPolicies.push(policy);
resourceAttributes.push({ resourceName, attributes, category });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function updateWalkthrough(context, defaultValuesFilename, serviceMetadata) {
const lexResources = {};

Object.keys(amplifyMeta[category]).forEach(resourceName => {
if (amplifyMeta[category][resourceName].service === serviceName) {
if (amplifyMeta[category][resourceName].service === serviceName && !!amplifyMeta[category][resourceName].providerPlugin) {
lexResources[resourceName] = amplifyMeta[category][resourceName];
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
const inquirer = require('inquirer');
const pinpointHelper = require('../../lib/pinpoint-helper');
const notificationManager = require('../../lib/notifications-manager');
const constants = require('../../lib/constants');
const multiEnvManager = require('../../lib/multi-env-manager');

module.exports = {
name: 'add',
alias: 'enable',
run: async context => {
context.exeInfo = context.amplify.getProjectDetails();

const categoryMeta = context.exeInfo.amplifyMeta[constants.CategoryName];
if (categoryMeta) {
const services = Object.keys(categoryMeta);
for (let i = 0; i < services.length; i++) {
const serviceMeta = categoryMeta[services[i]];

if (!serviceMeta.providerPlugin) {
context.print.error('Notifications is migrated from Mobile Hub and channels cannot be added with Amplify CLI.');
return context;
}
}
}

const availableChannels = notificationManager.getAvailableChannels(context);
const disabledChannels = notificationManager.getDisabledChannels(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ module.exports = {
}

await pinpointHelper.ensurePinpointApp(context);
await notificationManager.configureChannel(context, channelName);
await multiEnvManager.writeData(context);
if (await notificationManager.configureChannel(context, channelName)) {
await multiEnvManager.writeData(context);
}

return context;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ module.exports = {
context.exeInfo = context.amplify.getProjectDetails();
const pinpointApp = pinpointHelper.getPinpointApp(context);
if (pinpointApp) {
const pinpointResource = context.exeInfo.amplifyMeta.notifications[pinpointApp.Name];

if (pinpointResource && !pinpointResource.providerPlugin) {
context.print.error('Notifications is migrated from Mobile Hub and cannot be removed with Amplify CLI.');
return context;
}

const availableChannels = notificationManager.getAvailableChannels(context);
const enabledChannels = notificationManager.getEnabledChannels(context);

Expand Down
76 changes: 50 additions & 26 deletions packages/amplify-category-notifications/lib/multi-env-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,43 +34,67 @@ async function constructPinpointNotificationsMeta(context) {
pinpointApp = teamProviderInfo[envName].categories[constants.CategoryName][constants.PinpointName];
}

let isMobileHubMigrated = false;

if (!pinpointApp) {
const analyticsMeta = amplifyMeta[constants.AnalyticsCategoryName];
pinpointApp = pinpointHelper.scanCategoryMetaForPinpoint(analyticsMeta);
}

const backendConfigFilePath = context.amplify.pathManager.getBackendConfigFilePath();
const backendConfig = context.amplify.readJsonFile(backendConfigFilePath);
if (backendConfig[constants.CategoryName]) {
const categoryConfig = backendConfig[constants.CategoryName];
const resources = Object.keys(categoryConfig);
for (let i = 0; i < resources.length; i++) {
serviceBackendConfig = categoryConfig[resources[i]];
if (serviceBackendConfig.service === constants.PinpointName) {
serviceBackendConfig.resourceName = resources[i];
break;
// Check if meta contains a resource without provider, so it is a migrated one.
if (analyticsMeta) {
for (const resourceName of Object.keys(analyticsMeta)) {
const resource = analyticsMeta[resourceName];

if (resource.service === 'Pinpoint' && !resource.providerPlugin) {
isMobileHubMigrated = true;
break;
}
}
}
}

if (pinpointApp) {
await notificationManager.pullAllChannels(context, pinpointApp);
pinpointNotificationsMeta = {
Name: pinpointApp.Name,
service: constants.PinpointName,
output: pinpointApp,
};
if (!isMobileHubMigrated) {
pinpointApp = pinpointHelper.scanCategoryMetaForPinpoint(analyticsMeta);
}
}

if (serviceBackendConfig) {
if (pinpointNotificationsMeta) {
pinpointNotificationsMeta.channels = serviceBackendConfig.channels;
} else {
pinpointNotificationsMeta = serviceBackendConfig;
// Special case, in case of mobile hub migrated projects there is no backend config, so skipping the next parts
// as all data is present in the service, no need for any updates.

if (!isMobileHubMigrated) {
const backendConfigFilePath = context.amplify.pathManager.getBackendConfigFilePath();
const backendConfig = context.amplify.readJsonFile(backendConfigFilePath);
if (backendConfig[constants.CategoryName]) {
const categoryConfig = backendConfig[constants.CategoryName];
const resources = Object.keys(categoryConfig);
for (let i = 0; i < resources.length; i++) {
serviceBackendConfig = categoryConfig[resources[i]];
if (serviceBackendConfig.service === constants.PinpointName) {
serviceBackendConfig.resourceName = resources[i];
break;
}
}
}

if (pinpointApp) {
await notificationManager.pullAllChannels(context, pinpointApp);
pinpointNotificationsMeta = {
Name: pinpointApp.Name,
service: constants.PinpointName,
output: pinpointApp,
};
}

if (serviceBackendConfig) {
if (pinpointNotificationsMeta) {
pinpointNotificationsMeta.channels = serviceBackendConfig.channels;
} else {
pinpointNotificationsMeta = serviceBackendConfig;
}
}

return pinpointNotificationsMeta;
}

return pinpointNotificationsMeta;
return undefined;
}

async function deletePinpointAppForEnv(context, envName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,16 @@ async function disableChannel(context, channelName) {
async function configureChannel(context, channelName) {
if (Object.keys(channelWorkers).indexOf(channelName) > -1) {
context.exeInfo.pinpointClient = await pintpointHelper.getPinpointClient(context, 'update');

if (!context.exeInfo.serviceMeta.providerPlugin) {
context.print.error('No resources to update.');
return false;
}

const channelWorker = require(path.join(__dirname, channelWorkers[channelName]));
await channelWorker.configure(context);

return true;
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/amplify-category-storage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ async function migrate(context) {
const providerController = require(`./provider-utils/${amplifyMeta[category][resourceName].providerPlugin}/index`);
if (providerController) {
migrateResourcePromises.push(
providerController.migrateResource(context, projectPath, amplifyMeta[category][resourceName].service, resourceName)
providerController.migrateResource(context, projectPath, amplifyMeta[category][resourceName].service, resourceName),
);
} else {
context.print.error(`Provider not configured for ${category}: ${resourceName}`);
Expand Down Expand Up @@ -62,13 +62,13 @@ async function getPermissionPolicies(context, resourceOpsMapping) {
? resourceOpsMapping[resourceName].service
: amplifyMeta[category][resourceName].service;

const providerController = require(`./provider-utils/${providerPlugin}/index`);
if (providerController) {
if (providerPlugin) {
const providerController = require(`./provider-utils/${providerPlugin}/index`);
const { policy, attributes } = providerController.getPermissionPolicies(
context,
service,
resourceName,
resourceOpsMapping[resourceName]
resourceOpsMapping[resourceName],
);
permissionPolicies.push(policy);
resourceAttributes.push({ resourceName, attributes, category });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function updateWalkthrough(context, defaultValuesFilename, serviceMetadata) {
const dynamoDbResources = {};

Object.keys(amplifyMeta[category]).forEach(resourceName => {
if (amplifyMeta[category][resourceName].service === serviceName) {
if (amplifyMeta[category][resourceName].service === serviceName && !!amplifyMeta[category][resourceName].providerPlugin) {
dynamoDbResources[resourceName] = amplifyMeta[category][resourceName];
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function updateWalkthrough(context, defaultValuesFilename, serviceMetada) {
const storageResources = {};

Object.keys(amplifyMeta[category]).forEach(resourceName => {
if (amplifyMeta[category][resourceName].service === serviceName) {
if (amplifyMeta[category][resourceName].service === serviceName && !!amplifyMeta[category][resourceName].providerPlugin) {
storageResources[resourceName] = amplifyMeta[category][resourceName];
}
});
Expand Down
Loading

0 comments on commit 5dfe287

Please sign in to comment.