Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(amplify-category-storage): headless support for S3 #8423

Merged
merged 8 commits into from
Oct 17, 2021
1,442 changes: 849 additions & 593 deletions .circleci/config.yml

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/amplify-category-storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
],
"dependencies": {
"amplify-cli-core": "1.31.1",
"amplify-headless-interface": "1.10.0",
"amplify-prompts": "1.2.0",
"amplify-util-import": "1.5.15",
"chalk": "^4.1.1",
Expand All @@ -32,7 +33,7 @@
"inquirer": "^7.3.3",
"lodash": "^4.17.21",
"promise-sequential": "^1.1.1",
"uuid": "^3.4.0"
"uuid": "^8.3.2"
},
"devDependencies": {
"aws-sdk": "^2.963.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const run = async (context: $TSContext) => {
const servicesMetadata = ((await import('../../provider-utils/supported-services')) as $TSAny).supportedServices;

const serviceSelection = await context.amplify.serviceSelectionPrompt(context, categoryName, servicesMetadata, undefined, nameOverrides);
const providerController = require(`../../provider-utils/${serviceSelection.providerName}`);
const providerController = await import(`../../provider-utils/${serviceSelection.providerName}`);

if (!providerController) {
printer.error('Provider not configured for this category');
Expand Down
17 changes: 3 additions & 14 deletions packages/amplify-category-storage/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
export const categoryName = 'storage';

export enum ServiceName {
S3 = 'S3',
DynamoDB = 'DynamoDB',
}

// keep in sync with ServiceName in amplify-category-function, but probably it will not change
export const FunctionServiceNameLambdaFunction = 'Lambda';

export const storageParamsFilename = 'storage-params.json';
export const templateFilenameMap = {
[ServiceName.S3]: 's3-cloudformation-template.json.ejs',
[ServiceName.DynamoDB]: 'dynamoDb-cloudformation-template.json.ejs',
};
export const apiCategoryName = 'api';
export const authCategoryName = 'auth';
export const functionCategoryName = 'function';
31 changes: 31 additions & 0 deletions packages/amplify-category-storage/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { $TSAny, $TSContext, $TSObject, stateManager } from 'amplify-cli-core';
import { printer } from 'amplify-prompts';
import {
validateAddStorageRequest,
validateImportStorageRequest,
validateRemoveStorageRequest,
validateUpdateStorageRequest,
} from 'amplify-util-headless-input';
import * as path from 'path';
import sequential from 'promise-sequential';
import { updateConfigOnEnvInit } from './provider-utils/awscloudformation';
import {
headlessAddStorage,
headlessImportStorage,
headlessRemoveStorage,
headlessUpdateStorage,
} from './provider-utils/awscloudformation/storage-configuration-helpers';
import { categoryName } from './constants';
export { categoryName as category } from './constants';

Expand Down Expand Up @@ -107,6 +119,25 @@ export async function executeAmplifyCommand(context: $TSContext) {
await commandModule.run(context);
}

export const executeAmplifyHeadlessCommand = async (context: $TSContext, headlessPayload: string) => {
switch (context.input.command) {
case 'add':
await headlessAddStorage(context, await validateAddStorageRequest(headlessPayload));
break;
case 'update':
await headlessUpdateStorage(context, await validateUpdateStorageRequest(headlessPayload));
break;
case 'remove':
await headlessRemoveStorage(context, await validateRemoveStorageRequest(headlessPayload));
break;
case 'import':
await headlessImportStorage(context, await validateImportStorageRequest(headlessPayload));
break;
default:
printer.error(`Headless mode for ${context.input.command} storage is not implemented yet`);
}
};

export async function handleAmplifyEvent(context: $TSContext, args: $TSAny) {
printer.info(`${categoryName} handleAmplifyEvent to be implemented`);
printer.info(`Received event args ${args}`);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const uuid = require('uuid');
const { v4: uuid } = require('uuid');

const getAllDefaults = project => {
const name = project.projectConfig.projectName.toLowerCase();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const uuid = require('uuid');
import { v4 as uuid } from 'uuid';

const getAllDefaults = project => {
export const getAllDefaults = (project: Project) => {
const name = project.projectConfig.projectName.toLowerCase();
const [shortId] = uuid().split('-');

Expand All @@ -17,17 +17,15 @@ const getAllDefaults = project => {
bucketName: `${name}${uuid().replace(/-/g, '')}`.substr(0, 47), // 63(max) - 10 (envName max) - 4(stack name) - 2(separators)
authPolicyName: `s3_amplify_${shortId}`,
unauthPolicyName: `s3_amplify_${shortId}`,

authRoleName,
unauthRoleName,
storageAccess: 'auth',
selectedGuestPermissions: ['s3:GetObject', 's3:ListBucket'],
selectedAuthenticatedPermissions: ['s3:GetObject', 's3:ListBucket'],
triggerFunction: 'NONE',
};

return defaults;
};

module.exports = {
getAllDefaults,
};
type Project = { projectConfig: { projectName: string } };
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { IS3Service } from 'amplify-util-import';
import { Bucket } from 'aws-sdk/clients/s3';
import Enquirer from 'enquirer';
import _ from 'lodash';
import uuid from 'uuid';
import { checkIfAuthExists, resourceAlreadyExists } from '../service-walkthroughs/s3-walkthrough';
import { v4 as uuid } from 'uuid';
import { resourceAlreadyExists } from '../service-walkthroughs/s3-walkthrough';
import { checkIfAuthExists } from '../storage-configuration-helpers';
import { importMessages } from './messages';
import {
ImportS3HeadlessParameters,
Expand Down Expand Up @@ -206,7 +207,7 @@ const createParameters = (providerName: string, bucketList: Bucket[]): S3ImportP
return questionParameters;
};

const updateStateFiles = async (
export const updateStateFiles = async (
context: $TSContext,
questionParameters: S3ImportParameters,
answers: S3ImportAnswers,
Expand Down Expand Up @@ -392,8 +393,6 @@ const headlessImport = async (
// Validate required parameters' presence and merge into parameters
const currentEnvSpecificParameters = ensureHeadlessParameters(resourceParameters, headlessParams);

const amplifyMeta = stateManager.getMeta();

// Validate the parameters, generate the missing ones and import the resource.
const questionParameters: S3ImportParameters = {
providerName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export enum ServiceName {
S3 = 'S3',
DynamoDB = 'DynamoDB',
}

export const storageParamsFilename = 'storage-params.json';
export const templateFilenameMap = {
[ServiceName.S3]: 's3-cloudformation-template.json.ejs',
[ServiceName.DynamoDB]: 'dynamoDb-cloudformation-template.json.ejs',
};

// keep in sync with ServiceName in amplify-category-function, but probably it will not change
export const FunctionServiceNameLambdaFunction = 'Lambda';

export const providerName = 'awscloudformation';