-
Notifications
You must be signed in to change notification settings - Fork 821
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14024 from aws-amplify/gen2-migrations-execute
feat: automate preprocessing steps for refactor
- Loading branch information
Showing
11 changed files
with
423 additions
and
281 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
packages/amplify-migration-template-gen/src/cfn-stack-updater.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { CloudFormationClient, DescribeStacksCommand, Parameter, UpdateStackCommand } from '@aws-sdk/client-cloudformation'; | ||
import { CFNTemplate } from './types'; | ||
import assert from 'node:assert'; | ||
|
||
const POLL_ATTEMPTS = 60; | ||
const POLL_INTERVAL_MS = 1500; | ||
const NO_UPDATES_MESSAGE = 'No updates are to be performed'; | ||
const CFN_IAM_CAPABILIY = 'CAPABILITY_NAMED_IAM'; | ||
const COMPLETION_STATE = '_COMPLETE'; | ||
export const UPDATE_COMPLETE = 'UPDATE_COMPLETE'; | ||
/** | ||
* Updates a stack with given template. If no updates are present, it no-ops. | ||
* @param cfnClient | ||
* @param stackName | ||
* @param parameters | ||
* @param templateBody | ||
* @param attempts number of attempts to poll CFN stack for update completion state. The interval between the polls is 1.5 seconds. | ||
*/ | ||
export async function tryUpdateStack( | ||
cfnClient: CloudFormationClient, | ||
stackName: string, | ||
parameters: Parameter[], | ||
templateBody: CFNTemplate, | ||
attempts = POLL_ATTEMPTS, | ||
): Promise<string> { | ||
try { | ||
await cfnClient.send( | ||
new UpdateStackCommand({ | ||
TemplateBody: JSON.stringify(templateBody), | ||
Parameters: parameters, | ||
StackName: stackName, | ||
Capabilities: [CFN_IAM_CAPABILIY], | ||
Tags: [], | ||
}), | ||
); | ||
return pollStackForCompletionState(cfnClient, stackName, attempts); | ||
} catch (e) { | ||
if (!e.message.includes(NO_UPDATES_MESSAGE)) { | ||
throw e; | ||
} | ||
return UPDATE_COMPLETE; | ||
} | ||
} | ||
|
||
/** | ||
* Polls a stack for completion state | ||
* @param cfnClient | ||
* @param stackName | ||
* @param attempts number of attempts to poll for completion. | ||
* @returns the stack status | ||
*/ | ||
async function pollStackForCompletionState(cfnClient: CloudFormationClient, stackName: string, attempts: number): Promise<string> { | ||
do { | ||
const { Stacks } = await cfnClient.send( | ||
new DescribeStacksCommand({ | ||
StackName: stackName, | ||
}), | ||
); | ||
const stack = Stacks?.[0]; | ||
assert(stack); | ||
const stackStatus = stack.StackStatus; | ||
assert(stackStatus); | ||
if (stackStatus?.endsWith(COMPLETION_STATE)) { | ||
return stackStatus; | ||
} | ||
await new Promise((res) => setTimeout(() => res(''), POLL_INTERVAL_MS)); | ||
attempts--; | ||
} while (attempts > 0); | ||
throw new Error(`Stack ${stackName} did not reach a completion state within the given time period.`); | ||
} |
34 changes: 34 additions & 0 deletions
34
packages/amplify-migration-template-gen/src/custom-test-matchers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { | ||
DescribeStackResourcesCommand, | ||
DescribeStackResourcesCommandInput, | ||
UpdateStackCommand, | ||
DescribeStacksCommand, | ||
DescribeStacksCommandInput, | ||
UpdateStackCommandInput, | ||
} from '@aws-sdk/client-cloudformation'; | ||
|
||
type CFNCommand = DescribeStackResourcesCommand | DescribeStacksCommand | UpdateStackCommand; | ||
type CFNCommandType = typeof DescribeStackResourcesCommand | typeof DescribeStacksCommand | typeof UpdateStackCommand; | ||
type CFNCommandInput = DescribeStackResourcesCommandInput | DescribeStacksCommandInput | UpdateStackCommandInput; | ||
|
||
export const toBeACloudFormationCommand = (actual: [CFNCommand], expectedInput: CFNCommandInput, expectedType: CFNCommandType) => { | ||
const actualInstance = actual[0]; | ||
expect(actualInstance.input).toEqual(expectedInput); | ||
const constructorName = actualInstance.constructor.name; | ||
const pass = constructorName === expectedType.prototype.constructor.name; | ||
|
||
return { | ||
pass, | ||
message: () => `expected ${actual} to be instance of ${constructorName}`, | ||
}; | ||
}; | ||
|
||
declare global { | ||
// Needed for custom matchers. | ||
// eslint-disable-next-line @typescript-eslint/no-namespace | ||
namespace jest { | ||
interface Matchers<R> { | ||
toBeACloudFormationCommand(expectedInput: CFNCommandInput, expectedType: CFNCommandType): R; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.