From 6ebb22428dca7f66e5913f172ac7fea1388d3176 Mon Sep 17 00:00:00 2001 From: Sachin Panemangalore <83682223+sachscode@users.noreply.github.com> Date: Fri, 5 Nov 2021 23:58:25 -0700 Subject: [PATCH] Ext overrides3 storage headless migrate (#8696) * (fix) s3 cli-ux loop until permission selected * (fix) storage unit-tests for prompter function change * (fix) auto-migrate on headless s3 storage api * (fix) enable migration in headless only if required * (fix) unit-test failing because of path incorrect Co-authored-by: Sachin Panemangalore --- .../s3-walkthrough.test.ts | 8 +++++--- .../service-walkthroughs/s3-questions.ts | 10 ++++++++-- .../service-walkthroughs/s3-resource-api.ts | 16 +++++++++++++--- .../s3-user-input-state.ts | 19 +++++++++++++++++++ .../service-walkthroughs/s3-walkthrough.ts | 17 +++++++++++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts b/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts index 4c3991d622d..077d085b71d 100644 --- a/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts +++ b/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts @@ -1,17 +1,17 @@ import { $TSAny, $TSContext, AmplifySupportedService, stateManager } from 'amplify-cli-core'; import { prompter } from 'amplify-prompts'; import * as uuid from 'uuid'; -import { MigrationParams, S3InputState } from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-user-input-state'; import { AmplifyS3ResourceStackTransform } from '../../../../provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform'; -import { addWalkthrough, updateWalkthrough } from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough'; import { S3AccessType, S3PermissionType, S3TriggerFunctionType, - S3UserInputs, + S3UserInputs } from '../../../../provider-utils/awscloudformation/service-walkthrough-types/s3-user-input-types'; import * as s3AuthAPI from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-auth-api'; import { S3CLITriggerUpdateMenuOptions, UserPermissionTypeOptions } from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-questions'; +import { MigrationParams, S3InputState } from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-user-input-state'; +import { addWalkthrough, updateWalkthrough } from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough'; jest.mock('amplify-cli-core'); jest.mock('amplify-prompts'); @@ -19,6 +19,8 @@ jest.mock('../../../../provider-utils/awscloudformation/service-walkthroughs/s3- jest.mock('../../../../provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform'); jest.mock('../../../../provider-utils/awscloudformation/service-walkthroughs/s3-auth-api'); jest.mock('uuid'); +jest.mock('path'); +jest.mock('fs-extra'); describe('add s3 walkthrough tests', () => { let mockContext: $TSContext; diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-questions.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-questions.ts index 4f248d59c6b..ac14e12571a 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-questions.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-questions.ts @@ -150,7 +150,13 @@ export async function askCRUDQuestion( const message = `What kind of access do you want for ${userRole} users?`; const choices = possibleCRUDOperations; const initialIndexes = getIndexArrayByValue(possibleCRUDOperations, roleDefaultValues); - const selectedPermissions = await prompter.pick<'many', string>(message, choices, { returnSize: 'many', initial: initialIndexes }); + let selectedPermissions; + do { + selectedPermissions = await prompter.pick<'many', string>(message, choices, { returnSize: 'many', initial: initialIndexes }); + if( !selectedPermissions || selectedPermissions.length <= 0 ){ + printer.warn('Select at least one option'); + } + } while( !selectedPermissions || selectedPermissions.length <= 0 ); return selectedPermissions as Array; } @@ -203,7 +209,7 @@ export async function askUpdateTriggerSelection( return triggerOperationAnswer as S3CLITriggerUpdateMenuOptions; } -export async function askAuthPermissionQuestion(context: $TSContext, defaultValues: S3UserInputs) { +export async function askAuthPermissionQuestion(context: $TSContext, defaultValues: S3UserInputs): Promise { const permissions: S3PermissionType[] = await askCRUDQuestion(S3UserAccessRole.AUTH, undefined, context, defaultValues); return permissions; } diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-resource-api.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-resource-api.ts index bf264e8b346..6d18f7d7460 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-resource-api.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-resource-api.ts @@ -2,7 +2,7 @@ import { $TSContext, AmplifyCategories, AmplifySupportedService, CLISubCommandTy import { AmplifyS3ResourceStackTransform } from '../cdk-stack-builder/s3-stack-transform'; import { S3UserInputTriggerFunctionParams, S3UserInputs } from '../service-walkthrough-types/s3-user-input-types'; import { S3InputState } from './s3-user-input-state'; -import { createNewLambdaAndUpdateCFN } from './s3-walkthrough'; +import { createNewLambdaAndUpdateCFN, migrateStorageCategory, isMigrateStorageRequired } from './s3-walkthrough'; /** * @returns Name of S3 resource or undefined @@ -28,7 +28,11 @@ export function s3GetResourceName(): string | undefined { * @returns */ export async function s3GetUserInput(context: $TSContext, s3ResourceName: string): Promise { - const cliInputsState = new S3InputState(s3ResourceName as string, undefined); + //migrate storage and fetch cliInputsState + if ( isMigrateStorageRequired(context, s3ResourceName) ){ + await migrateStorageCategory(context, s3ResourceName); + } + let cliInputsState = new S3InputState(s3ResourceName as string, undefined); return cliInputsState.getUserInput(); } @@ -37,7 +41,7 @@ export async function s3GetUserInput(context: $TSContext, s3ResourceName: string * @param context * @returns triggerFunction name or undefined */ -export async function s3GetAdminTriggerFunctionName(context: $TSContext){ +export async function s3GetAdminTriggerFunctionName(context: $TSContext) : Promise { const s3ResourceName : string|undefined = await s3GetResourceName(); const s3UserInput :S3UserInputs | undefined = (s3ResourceName)?await s3GetUserInput(context , s3ResourceName ):undefined; return s3UserInput?.adminTriggerFunction?.triggerFunction; @@ -194,8 +198,14 @@ export async function addLambdaTrigger( /** HELPERS */ async function s3APIHelperTransformAndSaveState(context: $TSContext, storageInput: S3UserInputs, phase: CLISubCommandType) { + //migrate storage and fetch cliInputsState + if ( phase != CLISubCommandType.ADD && isMigrateStorageRequired(context, storageInput.resourceName as string) ){ + await migrateStorageCategory(context, storageInput.resourceName as string); + } + //Save CLI Inputs payload let cliInputsState; + if ( phase === CLISubCommandType.ADD ){ cliInputsState = new S3InputState(storageInput.resourceName as string, storageInput); } else { diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-user-input-state.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-user-input-state.ts index 010acc0b7ec..fd19ee19c26 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-user-input-state.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-user-input-state.ts @@ -191,8 +191,27 @@ export class S3InputState { fs.removeSync(migrationParams.storageParamsFilepath); } } + public checkNeedsMigration():boolean{ + const backendDir = pathManager.getBackendDirPath(); + const oldParametersFilepath = path.join(backendDir, AmplifyCategories.STORAGE, this._resourceName, 'parameters.json'); + const oldCFNFilepath = path.join( + backendDir, + AmplifyCategories.STORAGE, + this._resourceName, + `${AmplifySupportedService.S3}-cloudformation-template.json`, + ); + if ( fs.existsSync(oldParametersFilepath) && fs.existsSync(oldCFNFilepath) ){ + return true; + }else { + return false; + } + } public async migrate(context: $TSContext) { + //check if migration is possible + if (!this.checkNeedsMigration() ){ + return; + } try { await migrateAuthDependencyResource(context); } catch (error) { diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts index 6a9a659fb3f..e96b1a12fce 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts @@ -12,6 +12,7 @@ import { CLISubCommandType, AmplifySupportedService, $TSMeta, + pathManager, } from 'amplify-cli-core'; import { S3InputState } from './s3-user-input-state'; import { S3UserInputs, S3TriggerFunctionType } from '../service-walkthrough-types/s3-user-input-types'; @@ -179,6 +180,22 @@ export async function updateWalkthrough(context: $TSContext) { } } +/** + * Check if Storage feature needs migration + * @param context + * @param resourceName - storage resource name + * @returns + */ +export function isMigrateStorageRequired(context : $TSContext, resourceName: string){ + const projectBackendDirPath = pathManager.getBackendDirPath(); + const cliInputsFilePath = path.resolve(path.join(projectBackendDirPath, AmplifyCategories.STORAGE, resourceName, 'cli-inputs.json')); + if ( !fs.existsSync(cliInputsFilePath) ){ + return true; + }else { + return false; + } +} + /** * Migrate workflow for S3 resource * - converts old context files into cliInputs and transforms into cloudformation.