diff --git a/.circleci/config.yml b/.circleci/config.yml index a360f846eb1..efd6c42ccf5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1127,14 +1127,6 @@ jobs: environment: TEST_SUITE: src/__tests__/function_5.test.ts CLI_REGION: eu-central-1 - defer-init-push-amplify_e2e_tests: - working_directory: ~/repo - docker: *ref_1 - resource_class: large - steps: *ref_4 - environment: - TEST_SUITE: src/__tests__/defer-init-push.test.ts - CLI_REGION: ap-northeast-1 configure-project-amplify_e2e_tests: working_directory: ~/repo docker: *ref_1 @@ -1142,7 +1134,7 @@ jobs: steps: *ref_4 environment: TEST_SUITE: src/__tests__/configure-project.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-northeast-1 api_4-amplify_e2e_tests: working_directory: ~/repo docker: *ref_1 @@ -1150,7 +1142,7 @@ jobs: steps: *ref_4 environment: TEST_SUITE: src/__tests__/api_4.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ap-southeast-1 schema-iterative-update-4-amplify_e2e_tests_pkg_linux: working_directory: ~/repo docker: *ref_1 @@ -1821,16 +1813,6 @@ jobs: TEST_SUITE: src/__tests__/function_5.test.ts CLI_REGION: eu-central-1 steps: *ref_5 - defer-init-push-amplify_e2e_tests_pkg_linux: - working_directory: ~/repo - docker: *ref_1 - resource_class: large - environment: - AMPLIFY_DIR: /home/circleci/repo/out - AMPLIFY_PATH: /home/circleci/repo/out/amplify-pkg-linux - TEST_SUITE: src/__tests__/defer-init-push.test.ts - CLI_REGION: ap-northeast-1 - steps: *ref_5 configure-project-amplify_e2e_tests_pkg_linux: working_directory: ~/repo docker: *ref_1 @@ -1839,7 +1821,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/out AMPLIFY_PATH: /home/circleci/repo/out/amplify-pkg-linux TEST_SUITE: src/__tests__/configure-project.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-northeast-1 steps: *ref_5 api_4-amplify_e2e_tests_pkg_linux: working_directory: ~/repo @@ -1849,7 +1831,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/out AMPLIFY_PATH: /home/circleci/repo/out/amplify-pkg-linux TEST_SUITE: src/__tests__/api_4.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ap-southeast-1 steps: *ref_5 workflows: version: 2 @@ -1968,15 +1950,15 @@ workflows: - containers-api-amplify_e2e_tests - interactions-amplify_e2e_tests - datastore-modelgen-amplify_e2e_tests - - defer-init-push-amplify_e2e_tests + - configure-project-amplify_e2e_tests - schema-iterative-update-2-amplify_e2e_tests - schema-data-access-patterns-amplify_e2e_tests - init-special-case-amplify_e2e_tests - - configure-project-amplify_e2e_tests + - api_4-amplify_e2e_tests + - auth_1-amplify_e2e_tests - feature-flags-amplify_e2e_tests - schema-versioned-amplify_e2e_tests - plugin-amplify_e2e_tests - - api_4-amplify_e2e_tests - done_with_pkg_linux_e2e_tests: requires: - schema-key-amplify_e2e_tests_pkg_linux @@ -1998,15 +1980,15 @@ workflows: - containers-api-amplify_e2e_tests_pkg_linux - interactions-amplify_e2e_tests_pkg_linux - datastore-modelgen-amplify_e2e_tests_pkg_linux - - defer-init-push-amplify_e2e_tests_pkg_linux + - configure-project-amplify_e2e_tests_pkg_linux - schema-iterative-update-2-amplify_e2e_tests_pkg_linux - schema-data-access-patterns-amplify_e2e_tests_pkg_linux - init-special-case-amplify_e2e_tests_pkg_linux - - configure-project-amplify_e2e_tests_pkg_linux + - api_4-amplify_e2e_tests_pkg_linux + - auth_1-amplify_e2e_tests_pkg_linux - feature-flags-amplify_e2e_tests_pkg_linux - schema-versioned-amplify_e2e_tests_pkg_linux - plugin-amplify_e2e_tests_pkg_linux - - api_4-amplify_e2e_tests_pkg_linux - amplify_migration_tests_latest: context: - amplify-ecr-image-pull @@ -2421,7 +2403,7 @@ workflows: filters: *ref_9 requires: - migration-api-key-migration1-amplify_e2e_tests - - defer-init-push-amplify_e2e_tests: + - configure-project-amplify_e2e_tests: context: *ref_7 post-steps: *ref_8 filters: *ref_9 @@ -2481,7 +2463,7 @@ workflows: filters: *ref_9 requires: - layer-amplify_e2e_tests - - configure-project-amplify_e2e_tests: + - api_4-amplify_e2e_tests: context: *ref_7 post-steps: *ref_8 filters: *ref_9 @@ -2541,12 +2523,6 @@ workflows: filters: *ref_9 requires: - auth_3-amplify_e2e_tests - - api_4-amplify_e2e_tests: - context: *ref_7 - post-steps: *ref_8 - filters: *ref_9 - requires: - - auth_1-amplify_e2e_tests - schema-iterative-update-4-amplify_e2e_tests_pkg_linux: context: &ref_10 - amplify-ecr-image-pull @@ -2869,7 +2845,7 @@ workflows: filters: *ref_12 requires: - migration-api-key-migration1-amplify_e2e_tests_pkg_linux - - defer-init-push-amplify_e2e_tests_pkg_linux: + - configure-project-amplify_e2e_tests_pkg_linux: context: *ref_10 post-steps: *ref_11 filters: *ref_12 @@ -2933,7 +2909,7 @@ workflows: filters: *ref_12 requires: - layer-amplify_e2e_tests_pkg_linux - - configure-project-amplify_e2e_tests_pkg_linux: + - api_4-amplify_e2e_tests_pkg_linux: context: *ref_10 post-steps: *ref_11 filters: *ref_12 @@ -2997,9 +2973,3 @@ workflows: filters: *ref_12 requires: - auth_3-amplify_e2e_tests_pkg_linux - - api_4-amplify_e2e_tests_pkg_linux: - context: *ref_10 - post-steps: *ref_11 - filters: *ref_12 - requires: - - auth_1-amplify_e2e_tests_pkg_linux diff --git a/packages/amplify-cli-core/src/index.ts b/packages/amplify-cli-core/src/index.ts index 96121085a8d..baec0561c1a 100644 --- a/packages/amplify-cli-core/src/index.ts +++ b/packages/amplify-cli-core/src/index.ts @@ -180,7 +180,6 @@ interface AmplifyToolkit { getProjectMeta: () => $TSMeta; getResourceStatus: (category?: $TSAny, resourceName?: $TSAny, providerName?: $TSAny, filteredResources?: $TSAny) => $TSAny; getResourceOutputs: () => $TSAny; - getTags: (context: $TSContext) => $TSAny; getWhen: () => $TSAny; inputValidation: (input: $TSAny) => $TSAny; listCategories: () => $TSAny; @@ -196,7 +195,7 @@ interface AmplifyToolkit { filteredResources?: { category: string; resourceName: string }[], ) => $TSAny; storeCurrentCloudBackend: () => $TSAny; - readJsonFile: (file: string) => $TSAny; + readJsonFile: () => $TSAny; removeEnvFromCloud: () => $TSAny; removeDeploymentSecrets: (context: $TSContext, category: string, resource: string) => void; removeResource: () => $TSAny; diff --git a/packages/amplify-cli/src/commands/push.ts b/packages/amplify-cli/src/commands/push.ts index 82fe294cefd..8efa0234b1e 100644 --- a/packages/amplify-cli/src/commands/push.ts +++ b/packages/amplify-cli/src/commands/push.ts @@ -2,7 +2,6 @@ import sequential from 'promise-sequential'; import ora from 'ora'; import { $TSContext, $TSObject, stateManager, exitOnNextTick } from 'amplify-cli-core'; import { getProviderPlugins } from '../extensions/amplify-helpers/get-provider-plugins'; -import { onSuccess } from '../init-steps/s9-onSuccess'; const spinner = ora(''); @@ -45,7 +44,6 @@ export const run = async (context: $TSContext) => { if (context.parameters.options.force) { context.exeInfo.forcePush = true; } - context.exeInfo.deferredInitCallback = onSuccess; await syncCurrentCloudBackend(context); return await context.amplify.pushResources(context); } catch (e) { diff --git a/packages/amplify-cli/src/extensions/amplify-helpers/envResourceParams.ts b/packages/amplify-cli/src/extensions/amplify-helpers/envResourceParams.ts index 49af880b43c..956f581c273 100644 --- a/packages/amplify-cli/src/extensions/amplify-helpers/envResourceParams.ts +++ b/packages/amplify-cli/src/extensions/amplify-helpers/envResourceParams.ts @@ -75,12 +75,7 @@ export function saveEnvResourceParameters(context: $TSContext, category: string, stateManager.setTeamProviderInfo(undefined, teamProviderInfo); // write hostedUIProviderCreds to deploymentSecrets const deploymentSecrets = stateManager.getDeploymentSecrets(); - let rootStackId; - try { - rootStackId = getRootStackId(); - } catch (err) { - return; - } + const rootStackId = getRootStackId(); if (hostedUIProviderCreds) { stateManager.setDeploymentSecrets( mergeDeploymentSecrets({ diff --git a/packages/amplify-cli/src/extensions/amplify-helpers/get-root-stack-id.ts b/packages/amplify-cli/src/extensions/amplify-helpers/get-root-stack-id.ts index 7dc9e095847..b1b285ae127 100644 --- a/packages/amplify-cli/src/extensions/amplify-helpers/get-root-stack-id.ts +++ b/packages/amplify-cli/src/extensions/amplify-helpers/get-root-stack-id.ts @@ -4,8 +4,8 @@ export function getRootStackId(): string { const teamProviderInfo = stateManager.getTeamProviderInfo(); const { envName } = stateManager.getLocalEnvInfo(); const envTeamProviderInfo = teamProviderInfo[envName]; - const stackId = envTeamProviderInfo?.awscloudformation?.StackId; - if (typeof stackId === 'string') { + if (envTeamProviderInfo && envTeamProviderInfo.awscloudformation) { + const stackId = envTeamProviderInfo.awscloudformation.StackId; return stackId.split('/')[2]; } throw new Error('Root stack Id not found'); diff --git a/packages/amplify-cli/src/extensions/amplify-helpers/resource-status.ts b/packages/amplify-cli/src/extensions/amplify-helpers/resource-status.ts index dbe2e6491e3..ac6d9c4fc5f 100644 --- a/packages/amplify-cli/src/extensions/amplify-helpers/resource-status.ts +++ b/packages/amplify-cli/src/extensions/amplify-helpers/resource-status.ts @@ -486,16 +486,12 @@ export async function showResourceTable(category, resourceName, filteredResource table(tableOptions, { format: 'markdown' }); - // in the case of a deferred init, need to also check there are resources in the project - // checking for length > 1 because for some reason the aws cfn provider is in the resources list but it's not a resource - const updateTags = tagsUpdated && allResources.length > 1; - - if (updateTags) { + if (tagsUpdated) { print.info('\nTag Changes Detected'); } const resourceChanged = - resourcesToBeCreated.length + resourcesToBeUpdated.length + resourcesToBeSynced.length + resourcesToBeDeleted.length > 0 || updateTags; + resourcesToBeCreated.length + resourcesToBeUpdated.length + resourcesToBeSynced.length + resourcesToBeDeleted.length > 0 || tagsUpdated; return resourceChanged; } diff --git a/packages/amplify-cli/src/init-steps/s9-onSuccess.ts b/packages/amplify-cli/src/init-steps/s9-onSuccess.ts index 4c7de3af5c1..940a772d858 100644 --- a/packages/amplify-cli/src/init-steps/s9-onSuccess.ts +++ b/packages/amplify-cli/src/init-steps/s9-onSuccess.ts @@ -6,7 +6,6 @@ import { getProviderPlugins } from '../extensions/amplify-helpers/get-provider-p import { insertAmplifyIgnore } from '../extensions/amplify-helpers/git-manager'; import { writeReadMeFile } from '../extensions/amplify-helpers/docs-manager'; import { initializeEnv } from '../initialize-env'; -import _ from 'lodash'; export async function onHeadlessSuccess(context: $TSContext) { const frontendPlugins = getFrontendPlugins(context); @@ -109,19 +108,12 @@ function generateLocalTagsFile(context: $TSContext) { } export function generateAmplifyMetaFile(context: $TSContext) { - const { projectPath } = context.exeInfo.localEnvInfo; - - const { isNewEnv } = context.exeInfo; - - // store amplifyMeta - const meta = isNewEnv ? {} : stateManager.getMeta(projectPath, { throwIfNotExist: false }) || {}; - _.merge(meta, context.exeInfo.amplifyMeta); - stateManager.setMeta(projectPath, meta); + if (context.exeInfo.isNewEnv) { + const { projectPath } = context.exeInfo.localEnvInfo; - // store current cloud meta - const currMeta = isNewEnv ? {} : stateManager.getCurrentMeta(projectPath, { throwIfNotExist: false }) || {}; - _.merge(currMeta, context.exeInfo.amplifyMeta); - stateManager.setCurrentMeta(projectPath, currMeta); + stateManager.setCurrentMeta(projectPath, context.exeInfo.amplifyMeta); + stateManager.setMeta(projectPath, context.exeInfo.amplifyMeta); + } } function generateNonRuntimeFiles(context: $TSContext) { diff --git a/packages/amplify-cli/src/initialize-env.ts b/packages/amplify-cli/src/initialize-env.ts index 953805580da..0679d9d99c1 100644 --- a/packages/amplify-cli/src/initialize-env.ts +++ b/packages/amplify-cli/src/initialize-env.ts @@ -81,12 +81,6 @@ export async function initializeEnv(context: $TSContext, currentAmplifyMeta?: $T await sequential(categoryInitializationTasks); - // this function can now be called on the push codepath in the case of a deffered root stack push - // in that case, we don't need to push here as that will happen automatically down the road - if (context?.input?.command === 'push') { - return; - } - if (context.exeInfo.forcePush === undefined) { context.exeInfo.forcePush = await context.amplify.confirmPrompt( 'Do you want to push your resources to the cloud for your environment?', diff --git a/packages/amplify-e2e-core/src/init/deleteProject.ts b/packages/amplify-e2e-core/src/init/deleteProject.ts index 782fdfdc84a..5af02b32229 100644 --- a/packages/amplify-e2e-core/src/init/deleteProject.ts +++ b/packages/amplify-e2e-core/src/init/deleteProject.ts @@ -2,9 +2,6 @@ import { nspawn as spawn, retry, getCLIPath, describeCloudFormationStack, getPro export const deleteProject = async (cwd: string, profileConfig?: any): Promise => { const { StackName: stackName, Region: region } = getProjectMeta(cwd).providers.awscloudformation; - if (!stackName || !region) { - return; - } await retry( () => describeCloudFormationStack(stackName, region, profileConfig), stack => stack.StackStatus.endsWith('_COMPLETE'), diff --git a/packages/amplify-e2e-core/src/init/initProjectHelper.ts b/packages/amplify-e2e-core/src/init/initProjectHelper.ts index 6ffcfd2aac8..f129161b888 100644 --- a/packages/amplify-e2e-core/src/init/initProjectHelper.ts +++ b/packages/amplify-e2e-core/src/init/initProjectHelper.ts @@ -367,18 +367,6 @@ export function amplifyInitSandbox(cwd: string, settings: {}): Promise { }); } -export function amplifyInitYes(cwd: string): Promise { - return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['init', '--yes'], { - cwd, - stripColors: true, - env: { - CLI_DEV_INTERNAL_DISABLE_AMPLIFY_APP_CREATION: '1', - }, - }).run((err: Error) => (err ? reject(err) : resolve())); - }); -} - export function amplifyVersion(cwd: string, expectedVersion: string, testingWithLatestCodebase = false): Promise { return new Promise((resolve, reject) => { spawn(getCLIPath(testingWithLatestCodebase), ['--version'], { cwd, stripColors: true }) diff --git a/packages/amplify-e2e-tests/src/__tests__/defer-init-push.test.ts b/packages/amplify-e2e-tests/src/__tests__/defer-init-push.test.ts deleted file mode 100644 index 9b1071dc439..00000000000 --- a/packages/amplify-e2e-tests/src/__tests__/defer-init-push.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - addFunction, - amplifyInitYes, - amplifyPushAuth, - createNewProjectDir, - deleteProject, - deleteProjectDir, - getLocalEnvInfo, - getTeamProviderInfo, - initJSProjectWithProfile, -} from 'amplify-e2e-core'; -import { addEnvironment, addEnvironmentYes, checkoutEnvironment, removeEnvironment } from '../environment/env'; - -describe('defer root stack push', () => { - let projRoot: string; - beforeEach(async () => { - projRoot = await createNewProjectDir('defer-init-push'); - }); - - afterEach(async () => { - await deleteProject(projRoot); - deleteProjectDir(projRoot); - }); - - it('does not create a root stack on interactive init', async () => { - await initJSProjectWithProfile(projRoot, { name: 'deferInitPush', envName: 'dev' }); - const tpi_before = getTeamProviderInfo(projRoot); - expect(tpi_before?.dev?.awscloudformation?.DeploymentBucketName).toBeUndefined(); - await addFunction(projRoot, { functionTemplate: 'Hello World' }, 'nodejs'); - await amplifyPushAuth(projRoot); - const tpi_after = getTeamProviderInfo(projRoot); - expect(tpi_after?.dev?.awscloudformation?.DeploymentBucketName).toBeDefined(); - }); - - it('does not create a root stack on interactive env add', async () => { - await initJSProjectWithProfile(projRoot, { name: 'deferInitPush', envName: 'dev' }); - const tpi_dev = getTeamProviderInfo(projRoot); - expect(tpi_dev?.dev?.awscloudformation?.DeploymentBucketName).toBeUndefined(); - await addEnvironment(projRoot, { envName: 'test' }); - const tpi_test = getTeamProviderInfo(projRoot); - expect(tpi_test?.test?.awscloudformation?.DeploymentBucketName).toBeUndefined(); - }); - - it('creates a root stack on headless init', async () => { - await amplifyInitYes(projRoot); - const tpi_after = getTeamProviderInfo(projRoot); - expect(tpi_after?.dev?.awscloudformation?.DeploymentBucketName).toBeDefined(); - }); - - it('creates a root stack on headless env add', async () => { - await initJSProjectWithProfile(projRoot, { name: 'deferInitPush', envName: 'dev' }); - const tpi_dev = getTeamProviderInfo(projRoot); - expect(tpi_dev?.dev?.awscloudformation?.DeploymentBucketName).toBeUndefined(); - await addEnvironmentYes(projRoot, { envName: 'test' }); - const tpi_test = getTeamProviderInfo(projRoot); - expect(tpi_test?.test?.awscloudformation?.DeploymentBucketName).toBeDefined(); - }); - - it('can checkout unpushed environment', async () => { - await initJSProjectWithProfile(projRoot, { name: 'deferInitPush', envName: 'dev' }); - const tpi_dev = getTeamProviderInfo(projRoot); - expect(tpi_dev?.dev?.awscloudformation?.DeploymentBucketName).toBeUndefined(); - await addEnvironment(projRoot, { envName: 'test' }); - const tpi_test = getTeamProviderInfo(projRoot); - expect(tpi_test?.test?.awscloudformation?.DeploymentBucketName).toBeUndefined(); - await checkoutEnvironment(projRoot, { envName: 'dev' }); - const localEnvInfo = getLocalEnvInfo(projRoot); - expect(localEnvInfo?.envName).toEqual('dev'); - }); - - it('can remove unpushed environment', async () => { - await initJSProjectWithProfile(projRoot, { name: 'deferInitPush', envName: 'dev' }); - await addEnvironment(projRoot, { envName: 'test' }); - await checkoutEnvironment(projRoot, { envName: 'dev' }); - const tpi_before = getTeamProviderInfo(projRoot); - expect(Object.keys(tpi_before).sort()).toEqual(['dev', 'test']); - await removeEnvironment(projRoot, { envName: 'test' }); - const tpi_after = getTeamProviderInfo(projRoot); - expect(Object.keys(tpi_after)).toEqual(['dev']); - }); -}); diff --git a/packages/amplify-e2e-tests/src/environment/env.ts b/packages/amplify-e2e-tests/src/environment/env.ts index 808b2cde33f..ed3f4ad7cce 100644 --- a/packages/amplify-e2e-tests/src/environment/env.ts +++ b/packages/amplify-e2e-tests/src/environment/env.ts @@ -26,18 +26,6 @@ export function addEnvironment(cwd: string, settings: { envName: string; numLaye }); } -export function addEnvironmentYes(cwd: string, settings: { envName: string }): Promise { - return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['env', 'add', '--yes', '--envName', settings.envName], { - cwd, - stripColors: true, - env: { - CLI_DEV_INTERNAL_DISABLE_AMPLIFY_APP_CREATION: '1', - }, - }).run((err: Error) => (err ? reject(err) : resolve())); - }); -} - export function addEnvironmentWithImportedAuth(cwd: string, settings: { envName: string; currentEnvName: string }): Promise { return new Promise((resolve, reject) => { spawn(getCLIPath(), ['env', 'add'], { cwd, stripColors: true }) diff --git a/packages/amplify-provider-awscloudformation/src/__tests__/initializer.test.ts b/packages/amplify-provider-awscloudformation/src/__tests__/initializer.test.ts index 9a1498a5754..606349b6408 100644 --- a/packages/amplify-provider-awscloudformation/src/__tests__/initializer.test.ts +++ b/packages/amplify-provider-awscloudformation/src/__tests__/initializer.test.ts @@ -33,10 +33,6 @@ describe('run', () => { amplify: { getTags: jest.fn(), }, - input: { - options: '--yes', - command: 'init', - }, }; CloudFormation_mock.mockImplementation( () => diff --git a/packages/amplify-provider-awscloudformation/src/delete-env.js b/packages/amplify-provider-awscloudformation/src/delete-env.js index ef5f268ad9f..d078b4bccd2 100644 --- a/packages/amplify-provider-awscloudformation/src/delete-env.js +++ b/packages/amplify-provider-awscloudformation/src/delete-env.js @@ -6,23 +6,19 @@ const { S3 } = require('./aws-utils/aws-s3'); const { deleteEnv } = require('./amplify-service-manager'); const { S3BackendZipFileName, ProviderName } = require('./constants'); const { downloadZip, extractZip } = require('./zip-util'); -const { stateManager } = require('amplify-cli-core'); async function run(context, envName, deleteS3) { const credentials = await loadConfigurationForEnv(context, envName); const cfn = await new Cloudformation(context, null, credentials); const s3 = await S3.getInstance(context, credentials); let removeBucket = false; - const deploymentBucketName = stateManager.getTeamProviderInfo()?.[envName]?.[ProviderName]?.DeploymentBucketName; + let deploymentBucketName; let storageCategoryBucketName; - // if this env has not been initialized in the cloud, early return - if (!deploymentBucketName) { - return; - } - if (deleteS3) { - if (!!deploymentBucketName && (await s3.ifBucketExists(deploymentBucketName))) { + const projectDetails = context.amplify.getProjectDetails(); + deploymentBucketName = projectDetails.teamProviderInfo[envName][ProviderName].DeploymentBucketName; + if (await s3.ifBucketExists(deploymentBucketName)) { const amplifyDir = context.amplify.pathManager.getAmplifyDirPath(); const tempDir = path.join(amplifyDir, envName, '.temp'); storageCategoryBucketName = await getStorageCategoryBucketNameFromCloud(context, envName, s3, tempDir); diff --git a/packages/amplify-provider-awscloudformation/src/ensure-root-stack.ts b/packages/amplify-provider-awscloudformation/src/ensure-root-stack.ts deleted file mode 100644 index 84d03d6c897..00000000000 --- a/packages/amplify-provider-awscloudformation/src/ensure-root-stack.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { $TSContext, stateManager } from 'amplify-cli-core'; -import constants from './constants'; -import { run as initializeRootStack } from './initializer'; - -/** - * Checks if the root stack exists. - * If not it is created and the deployment bucket is populated with current cloud backend and other meta files - */ -export const ensureRootStack = async (context: $TSContext): Promise<$TSContext> => { - if (rootStackExists()) { - return context; - } - await initializeRootStack(context); - await context.exeInfo.deferredInitCallback(context); - return context; -}; - -export const rootStackExists = () => { - const meta = stateManager.getMeta(); - return !!meta?.providers?.[constants.ProviderName]?.DeploymentBucketName; -}; diff --git a/packages/amplify-provider-awscloudformation/src/initialize-env.ts b/packages/amplify-provider-awscloudformation/src/initialize-env.ts index b8d5bb17420..6825d6de3f9 100644 --- a/packages/amplify-provider-awscloudformation/src/initialize-env.ts +++ b/packages/amplify-provider-awscloudformation/src/initialize-env.ts @@ -8,33 +8,25 @@ const { downloadZip, extractZip } = require('./zip-util'); const { S3BackendZipFileName } = require('./constants'); const { fileLogger } = require('./utils/aws-logger'); const logger = fileLogger('initialize-env'); -import { JSONUtilities, PathConstants, stateManager, $TSMeta, $TSContext, pathManager } from 'amplify-cli-core'; -import { ProviderName as providerName } from './constants'; -import { rootStackExists } from './ensure-root-stack'; +import { JSONUtilities, PathConstants, stateManager, $TSMeta, $TSContext } from 'amplify-cli-core'; export async function run(context: $TSContext, providerMetadata: $TSMeta) { if (context.exeInfo && context.exeInfo.isNewEnv) { return context; } - // empty #current-cloud-backend dir and reset default meta file - resetCurrentCloudBackend(); - - // if this environment is not pushed yet, early return - if (!rootStackExists()) { - return context; - } - - const amplifyDir = pathManager.getAmplifyDirPath(); + const amplifyDir = context.amplify.pathManager.getAmplifyDirPath(); const tempDir = path.join(amplifyDir, '.temp'); - const currentCloudBackendDir = pathManager.getCurrentCloudBackendDirPath(); - const backendDir = pathManager.getBackendDirPath(); + const currentCloudBackendDir = context.amplify.pathManager.getCurrentCloudBackendDirPath(); + const backendDir = context.amplify.pathManager.getBackendDirPath(); const s3 = await S3.getInstance(context); const cfnItem = await new Cloudformation(context); const file = await downloadZip(s3, tempDir, S3BackendZipFileName); const unzippeddir = await extractZip(tempDir, file); + fs.removeSync(currentCloudBackendDir); + // Move out cli.*json if exists in the temp directory into the amplify directory before copying backand and // current cloud backend directories. const cliJSONFiles = glob.sync(PathConstants.CLIJSONFileNameGlob, { @@ -116,16 +108,4 @@ export async function run(context: $TSContext, providerMetadata: $TSMeta) { if (hasMigratedResources) { stateManager.setCurrentMeta(undefined, amplifyMeta); } - return context; } - -const resetCurrentCloudBackend = () => { - const currentCloudBackendDir = pathManager.getCurrentCloudBackendDirPath(); - fs.removeSync(currentCloudBackendDir); - fs.ensureDirSync(currentCloudBackendDir); - stateManager.setCurrentMeta(undefined, { - providers: { - [providerName]: {}, - }, - }); -}; diff --git a/packages/amplify-provider-awscloudformation/src/initializer.ts b/packages/amplify-provider-awscloudformation/src/initializer.js similarity index 61% rename from packages/amplify-provider-awscloudformation/src/initializer.ts rename to packages/amplify-provider-awscloudformation/src/initializer.js index 929cbd043bf..44f269c6315 100644 --- a/packages/amplify-provider-awscloudformation/src/initializer.ts +++ b/packages/amplify-provider-awscloudformation/src/initializer.js @@ -1,9 +1,6 @@ -import { $TSContext, $TSAny, pathManager, PathConstants, stateManager, JSONUtilities } from 'amplify-cli-core'; -import _ from 'lodash'; -import * as configurationManager from './configuration-manager'; - const moment = require('moment'); const path = require('path'); +const { pathManager, PathConstants, stateManager, JSONUtilities } = require('amplify-cli-core'); const glob = require('glob'); const archiver = require('./utils/archiver'); const fs = require('fs-extra'); @@ -12,16 +9,84 @@ const sequential = require('promise-sequential'); const Cloudformation = require('./aws-utils/aws-cfn'); const { S3 } = require('./aws-utils/aws-s3'); const constants = require('./constants'); +const configurationManager = require('./configuration-manager'); const amplifyServiceManager = require('./amplify-service-manager'); const amplifyServiceMigrate = require('./amplify-service-migrate'); const { fileLogger } = require('./utils/aws-logger'); const { prePushCfnTemplateModifier } = require('./pre-push-cfn-processor/pre-push-cfn-modifier'); const logger = fileLogger('attach-backend'); -export async function run(context) { +async function run(context) { await configurationManager.init(context); - if (doInitializeInCloud(context)) { - await initializeRootStack(context); + if (!context.exeInfo || context.exeInfo.isNewEnv) { + context.exeInfo = context.exeInfo || {}; + const { projectName } = context.exeInfo.projectConfig; + const initTemplateFilePath = path.join(__dirname, '..', 'resources', 'rootStackTemplate.json'); + const timeStamp = `${moment().format('Hmmss')}`; + const { envName = '' } = context.exeInfo.localEnvInfo; + let stackName = normalizeStackName(`amplify-${projectName}-${envName}-${timeStamp}`); + const awsConfig = await configurationManager.getAwsConfig(context); + + const amplifyServiceParams = { + context, + awsConfig, + projectName, + envName, + stackName, + }; + const { amplifyAppId, verifiedStackName, deploymentBucketName } = await amplifyServiceManager.init(amplifyServiceParams); + + stackName = verifiedStackName; + const Tags = context.amplify.getTags(context); + + const authRoleName = `${stackName}-authRole`; + const unauthRoleName = `${stackName}-unauthRole`; + + const rootStack = JSONUtilities.readJson(initTemplateFilePath); + await prePushCfnTemplateModifier(rootStack); + // Track Amplify Console generated stacks + if (!!process.env.CLI_DEV_INTERNAL_DISABLE_AMPLIFY_APP_DELETION) { + rootStack.Description = 'Root Stack for AWS Amplify Console'; + } + + const params = { + StackName: stackName, + Capabilities: ['CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'], + TemplateBody: JSON.stringify(rootStack), + Parameters: [ + { + ParameterKey: 'DeploymentBucketName', + ParameterValue: deploymentBucketName, + }, + { + ParameterKey: 'AuthRoleName', + ParameterValue: authRoleName, + }, + { + ParameterKey: 'UnauthRoleName', + ParameterValue: unauthRoleName, + }, + ], + Tags, + }; + + const spinner = ora(); + spinner.start('Initializing project in the cloud...'); + + try { + const cfnItem = await new Cloudformation(context, 'init', awsConfig); + const stackDescriptionData = await cfnItem.createResourceStack(params); + + processStackCreationData(context, amplifyAppId, stackDescriptionData); + cloneCLIJSONForNewEnvironment(context); + + spinner.succeed('Successfully created initial AWS cloud resources for deployments.'); + + return context; + } catch (e) { + spinner.fail('Root stack creation failed'); + throw e; + } } else if ( // This part of the code is invoked by the `amplify init --appId xxx` command // on projects that are already fully setup by `amplify init` with the Amplify CLI version prior to 4.0.0. @@ -35,10 +100,7 @@ export async function run(context) { context.exeInfo.inputParams.amplify.appId ) { await amplifyServiceMigrate.run(context); - } else { - setCloudFormationOutputInContext(context, {}); } - cloneCLIJSONForNewEnvironment(context); } function processStackCreationData(context, amplifyAppId, stackDescriptiondata) { @@ -51,7 +113,18 @@ function processStackCreationData(context, amplifyAppId, stackDescriptiondata) { if (amplifyAppId) { metadata[constants.AmplifyAppIdLabel] = amplifyAppId; } - setCloudFormationOutputInContext(context, metadata); + + context.exeInfo.amplifyMeta = {}; + if (!context.exeInfo.amplifyMeta.providers) { + context.exeInfo.amplifyMeta.providers = {}; + } + context.exeInfo.amplifyMeta.providers[constants.ProviderName] = metadata; + + if (context.exeInfo.isNewEnv) { + const { envName } = context.exeInfo.localEnvInfo; + context.exeInfo.teamProviderInfo[envName] = {}; + context.exeInfo.teamProviderInfo[envName][constants.ProviderName] = metadata; + } } else { throw new Error('No stack data present'); } @@ -77,79 +150,9 @@ function cloneCLIJSONForNewEnvironment(context) { } } -async function initializeRootStack(context: $TSContext) { - context.exeInfo = context.exeInfo || {}; - const { projectName } = context.exeInfo.projectConfig; - const initTemplateFilePath = path.join(__dirname, '..', 'resources', 'rootStackTemplate.json'); - const timeStamp = `${moment().format('Hmmss')}`; - const { envName = '' } = context.exeInfo.localEnvInfo; - let stackName = normalizeStackName(`amplify-${projectName}-${envName}-${timeStamp}`); - const awsConfig = await configurationManager.getAwsConfig(context); - - const amplifyServiceParams = { - context, - awsConfig, - projectName, - envName, - stackName, - }; - const { amplifyAppId, verifiedStackName, deploymentBucketName } = await amplifyServiceManager.init(amplifyServiceParams); - - stackName = verifiedStackName; - const Tags = context.amplify.getTags(context); - - const authRoleName = `${stackName}-authRole`; - const unauthRoleName = `${stackName}-unauthRole`; - - const rootStack = JSONUtilities.readJson<$TSAny>(initTemplateFilePath); - await prePushCfnTemplateModifier(rootStack); - // Track Amplify Console generated stacks - if (!!process.env.CLI_DEV_INTERNAL_DISABLE_AMPLIFY_APP_DELETION) { - rootStack.Description = 'Root Stack for AWS Amplify Console'; - } - - const params = { - StackName: stackName, - Capabilities: ['CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'], - TemplateBody: JSON.stringify(rootStack), - Parameters: [ - { - ParameterKey: 'DeploymentBucketName', - ParameterValue: deploymentBucketName, - }, - { - ParameterKey: 'AuthRoleName', - ParameterValue: authRoleName, - }, - { - ParameterKey: 'UnauthRoleName', - ParameterValue: unauthRoleName, - }, - ], - Tags, - }; - - const spinner = ora(); - spinner.start('Initializing project in the cloud...'); - - try { - const cfnItem = await new Cloudformation(context, 'init', awsConfig); - const stackDescriptionData = await cfnItem.createResourceStack(params); - - processStackCreationData(context, amplifyAppId, stackDescriptionData); - - spinner.succeed('Successfully created initial AWS cloud resources for deployments.'); - - return context; - } catch (e) { - spinner.fail('Root stack creation failed'); - throw e; - } -} - -export async function onInitSuccessful(context: $TSContext) { +async function onInitSuccessful(context) { configurationManager.onInitSuccessful(context); - if (doInitializeInCloud(context)) { + if (context.exeInfo.isNewEnv) { context = await storeCurrentCloudBackend(context); await storeArtifactsForAmplifyService(context); } @@ -220,15 +223,6 @@ function storeArtifactsForAmplifyService(context) { }); } -function setCloudFormationOutputInContext(context: $TSContext, cfnOutput: object) { - _.set(context, ['exeInfo', 'amplifyMeta', 'providers', constants.ProviderName], cfnOutput); - - const { envName } = context.exeInfo.localEnvInfo; - if (envName) { - _.set(context, ['exeInfo', 'teamProviderInfo', envName, constants.ProviderName], cfnOutput); - } -} - async function uploadFile(s3, filePath, key) { if (fs.existsSync(filePath)) { const s3Params = { @@ -254,10 +248,7 @@ function normalizeStackName(stackName) { return result; } -const doInitializeInCloud = (context: $TSContext): boolean => { - const hasCommandLineArgs = !_.isEmpty(context?.input?.options); - const isHeadlessInit = context?.input?.command === 'init' && hasCommandLineArgs; - const isHeadlessEnvAdd = context?.input?.command === 'env' && context?.input?.subCommands?.[0] === 'add' && hasCommandLineArgs; - const isPush = context?.input?.command === 'push'; - return !context.exeInfo || (context.exeInfo.isNewEnv && isHeadlessInit) || (context.exeInfo.isNewEnv && isHeadlessEnvAdd) || isPush; +module.exports = { + run, + onInitSuccessful, }; diff --git a/packages/amplify-provider-awscloudformation/src/push-resources.ts b/packages/amplify-provider-awscloudformation/src/push-resources.ts index f939775af87..e6cd5eab0f4 100644 --- a/packages/amplify-provider-awscloudformation/src/push-resources.ts +++ b/packages/amplify-provider-awscloudformation/src/push-resources.ts @@ -43,7 +43,6 @@ import { APIGW_AUTH_STACK_LOGICAL_ID, loadApiWithPrivacyParams } from './utils/c import { createEnvLevelConstructs } from './utils/env-level-constructs'; import { NETWORK_STACK_LOGICAL_ID } from './network/stack'; import { preProcessCFNTemplate } from './pre-push-cfn-processor/cfn-pre-processor'; -import { ensureRootStack } from './ensure-root-stack'; import { AUTH_TRIGGER_STACK, AUTH_TRIGGER_TEMPLATE } from './utils/upload-auth-trigger-template'; import { ensureValidFunctionModelDependencies } from './utils/remove-dependent-function'; @@ -69,7 +68,6 @@ const deploymentInProgressErrorMessage = (context: $TSContext) => { }; export async function run(context: $TSContext, resourceDefinition: $TSObject) { - context = await ensureRootStack(context); const deploymentStateManager = await DeploymentStateManager.createDeploymentStateManager(context); let iterativeDeploymentWasInvoked = false;