-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(aws-cdk): added tools to deploy to AWS
- Loading branch information
Showing
30 changed files
with
367 additions
and
7,650 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
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,38 @@ | ||
{ | ||
"name": "@nzyme/aws-cdk", | ||
"version": "1.0.0", | ||
"type": "module", | ||
"main": "./dist/index.js", | ||
"exports": { | ||
".": { | ||
"source": "./src/index.ts", | ||
"import": "./dist/index.js" | ||
} | ||
}, | ||
"types": "./src/index.ts", | ||
"sideEffects": false, | ||
"repository": "https://github.com/nzymejs/nzyme.git", | ||
"author": "Michał Kędrzyński <m.kedrzynski@gmail.com>", | ||
"dependencies": { | ||
"@aws-cdk/cloudformation-diff": "^2.73.0", | ||
"@aws-cdk/core": "1.202.0", | ||
"@babel/preset-env": "^7.22.4", | ||
"@nzyme/ioc": "1.0.0", | ||
"@nzyme/utils": "1.0.0", | ||
"aws-cdk": "2.81.0", | ||
"cdk-assets": "^2.60.0", | ||
"chalk": "^5.2.0", | ||
"consola": "^3.1.0", | ||
"promptly": "^3.2.0", | ||
"proxy-agent": "^5.0.0" | ||
}, | ||
"depcheck": { | ||
"ignoreDeps": [ | ||
"aws-sdk", | ||
"promptly", | ||
"proxy-agent", | ||
"cdk-assets", | ||
"@babel/preset-env" | ||
] | ||
} | ||
} |
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,133 @@ | ||
import { diffTemplate, formatDifferences } from '@aws-cdk/cloudformation-diff'; | ||
import * as cdk from '@aws-cdk/core'; | ||
import { SdkProvider } from 'aws-cdk/lib/api/aws-auth/index.js'; | ||
import { Bootstrapper } from 'aws-cdk/lib/api/bootstrap/index.js'; | ||
import { AssetManifestArtifact, CloudFormationStackArtifact } from '@aws-cdk/cx-api'; | ||
import { Deployments } from 'aws-cdk/lib/api/deployments.js'; | ||
import { WorkGraphBuilder } from 'aws-cdk/lib/util/work-graph-builder.js'; | ||
import chalk from 'chalk'; | ||
import consola from 'consola'; | ||
|
||
import { arrayReverse } from '@nzyme/utils'; | ||
|
||
import { Stack } from './Stack.js'; | ||
|
||
export interface AppOptions { | ||
readonly sdkProvider: SdkProvider; | ||
} | ||
|
||
export class App extends cdk.App { | ||
private readonly sdkProvider: SdkProvider; | ||
private readonly deployments: Deployments; | ||
|
||
constructor(options: AppOptions) { | ||
super(); | ||
this.sdkProvider = options.sdkProvider; | ||
this.deployments = new Deployments({ sdkProvider: this.sdkProvider }); | ||
} | ||
|
||
public get stacks() { | ||
return this.node.children.filter(child => child instanceof Stack) as Stack[]; | ||
} | ||
|
||
/** | ||
* Bootstrapping environment is required for stacks using cross-region resources, like CloudFront. | ||
*/ | ||
public async bootstrap() { | ||
const bootstrapper = new Bootstrapper({ | ||
source: 'default', | ||
}); | ||
|
||
const region = this.sdkProvider.defaultRegion; | ||
const account = (await this.sdkProvider.defaultAccount())?.accountId; | ||
if (!account) { | ||
throw new Error('No AWS account detected.'); | ||
} | ||
|
||
return await bootstrapper.bootstrapEnvironment( | ||
{ | ||
name: '', | ||
region, | ||
account, | ||
}, | ||
this.sdkProvider, | ||
); | ||
} | ||
|
||
public async build() { | ||
for (const stack of this.stacks) { | ||
await stack.$.execute(); | ||
} | ||
} | ||
|
||
public async deploy() { | ||
await this.build(); | ||
|
||
const cloudAssembly = this.synth(); | ||
const stacks = this.stacks; | ||
|
||
for (const artifact of cloudAssembly.artifacts) { | ||
if (artifact instanceof CloudFormationStackArtifact) { | ||
const stack = stacks.find(stack => stack.stackName === artifact.stackName); | ||
const stackName = artifact.stackName; | ||
|
||
consola.info(`Deploying stack ${chalk.green(stackName)}`); | ||
stack?.$.emit('deploy:start'); | ||
|
||
const deployment = await this.deployments.deployStack({ | ||
stack: artifact, | ||
deployName: artifact.stackName, | ||
}); | ||
|
||
consola.success(`Successfully deployed stack ${chalk.green(stackName)}`); | ||
stack?.$.emit('deploy:finished', deployment); | ||
} | ||
} | ||
} | ||
|
||
public async destroy() { | ||
const cloudAssembly = this.synth(); | ||
|
||
// Destroy stacks in reverse order. | ||
for (const stack of arrayReverse(this.stacks)) { | ||
const stackName = stack.stackName; | ||
const region = stack.region ?? this.sdkProvider.defaultRegion; | ||
|
||
consola.info(`Destroying stack ${chalk.green(stackName)} in ${chalk.green(region)}`); | ||
stack.$.emit('destroy:start'); | ||
|
||
await this.deployments.destroyStack({ | ||
stack: cloudAssembly.getStackByName(stackName), | ||
}); | ||
|
||
consola.success(`Successfully destroyed stack ${chalk.green(stackName)}`); | ||
stack.$.emit('destroy:finished'); | ||
} | ||
} | ||
|
||
public async diff() { | ||
await this.build(); | ||
|
||
const cloudAssembly = this.synth(); | ||
const stacks = this.stacks; | ||
|
||
for (const artifact of cloudAssembly.artifacts) { | ||
if (artifact instanceof CloudFormationStackArtifact) { | ||
const currentTemplate = await this.deployments.readCurrentTemplateWithNestedStacks( | ||
artifact, | ||
); | ||
|
||
const diff = diffTemplate(currentTemplate, artifact.template); | ||
|
||
if (diff.isEmpty) { | ||
consola.success( | ||
`No changes detected for stack ${chalk.green(artifact.stackName)}`, | ||
); | ||
} else { | ||
consola.info(`Changes for stack ${chalk.green(artifact.stackName)}:\n`); | ||
formatDifferences(process.stdout, diff); | ||
} | ||
} | ||
} | ||
} | ||
} |
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,75 @@ | ||
import * as cdk from '@aws-cdk/core'; | ||
import { CfnOutput } from '@aws-cdk/core'; | ||
import { DeployStackResult } from 'aws-cdk/lib/api'; | ||
|
||
import { eventEmitter } from '@nzyme/utils'; | ||
|
||
import { App } from './App.js'; | ||
|
||
export interface StackOptions { | ||
readonly name: string; | ||
readonly env?: cdk.Environment; | ||
} | ||
|
||
export interface StackEvents { | ||
'deploy:start': void; | ||
'deploy:finished': DeployStackResult; | ||
'destroy:start': void; | ||
'destroy:finished': void; | ||
} | ||
|
||
export type StackHandler = () => Promise<void>; | ||
|
||
export class Stack extends cdk.Stack { | ||
private readonly eventEmitter = eventEmitter<StackEvents>(); | ||
private readonly tasks: StackHandler[] = []; | ||
|
||
private deployResult: DeployStackResult | undefined; | ||
|
||
constructor(app: App, public readonly options: StackOptions) { | ||
super(app, options.name, { env: options.env }); | ||
|
||
this.on('deploy:start', () => { | ||
this.deployResult = undefined; | ||
}); | ||
|
||
this.on('deploy:finished', result => { | ||
this.deployResult = result; | ||
}); | ||
} | ||
|
||
public readonly on = this.eventEmitter.on; | ||
|
||
/** Internal */ | ||
public readonly $ = { | ||
emit: this.eventEmitter.emit, | ||
execute: async () => { | ||
for (const task of this.tasks) { | ||
await task(); | ||
} | ||
}, | ||
}; | ||
|
||
public enqueue(handler: StackHandler) { | ||
this.tasks.push(handler); | ||
} | ||
|
||
public createExport(name: string, value: string) { | ||
if (!/\w+/.test(name)) { | ||
throw new Error('Export name can only contain letters and numbers.'); | ||
} | ||
|
||
const output = new CfnOutput(this, name, { | ||
value, | ||
exportName: name, | ||
}); | ||
|
||
return () => { | ||
if (this.deployResult) { | ||
return this.deployResult.outputs[name]; | ||
} | ||
|
||
return cdk.Fn.importValue(output.importValue); | ||
}; | ||
} | ||
} |
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,5 @@ | ||
import { SdkProvider } from 'aws-cdk/lib/api/aws-auth/index.js'; | ||
|
||
export function getSdkProvider() { | ||
return SdkProvider.withAwsCliCompatibleDefaults({}); | ||
} |
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,3 @@ | ||
export * from './App.js'; | ||
export * from './Stack.js'; | ||
export * from './getSdkProvider.js'; |
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,4 @@ | ||
{ | ||
"extends": "./tsconfig.json", | ||
"include": ["./src/**/*.ts", "./tests/**/*.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,17 @@ | ||
{ | ||
"extends": "../../tsconfig.base.json", | ||
"compilerOptions": { | ||
"baseUrl": ".", | ||
"outDir": "./dist", | ||
"rootDir": "./src" | ||
}, | ||
"include": ["src"], | ||
"references": [ | ||
{ | ||
"path": "../ioc/tsconfig.json" | ||
}, | ||
{ | ||
"path": "../utils/tsconfig.json" | ||
} | ||
] | ||
} |
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
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 |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
"include": ["src"], | ||
"references": [ | ||
{ | ||
"path": "../types/tsconfig.json" | ||
"path": "../utils/tsconfig.json" | ||
} | ||
] | ||
} |
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
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
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 |
---|---|---|
@@ -1,5 +1,6 @@ | ||
export * from './Container.js'; | ||
export * from './Injectable.js'; | ||
export * from './Service.js'; | ||
export * from './Executable.js'; | ||
export * from './Factory.js'; | ||
export * from './Injectable.js'; | ||
export * from './Resolvable.js'; | ||
export * from './Service.js'; |
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.