Skip to content

Commit

Permalink
feat(awscdk): awscdk-java-app (projen#1190)
Browse files Browse the repository at this point in the history
Introduce an AWS CDK Java app project (`awscdk-java-app`). This is needed as a basis for adding support for AWS Lambda functions in Java (projen#1070).

Extracts some common CDK app logic into components (`awscdk.CdkConfig` and `awscdk.CdkTasks`).

BREAKING CHANGE: `CdkApprovalLevel` is now `awscdk.ApprovalLevel`.
* **awscdk:** `cdkTypeScriptApp.cdkConfig` now refers to a `awscdk.CdkConfig` object. To add custom fields to `cdk.json` use `cdkTypeScriptApp.cdkConfig.json`.

---
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
  • Loading branch information
Elad Ben-Israel authored Oct 31, 2021
1 parent bff7bc8 commit b7753ec
Show file tree
Hide file tree
Showing 14 changed files with 1,809 additions and 119 deletions.
347 changes: 329 additions & 18 deletions API.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Currently supported project types (use `npx projen new` without a type for a
list):

<!-- <macro exec="node ./scripts/readme-projects.js"> -->
* [awscdk-app-java](https://github.com/projen/projen/blob/main/API.md#projen-awscdk-awscdkjavaapp) - AWS CDK app in Java.
* [awscdk-app-ts](https://github.com/projen/projen/blob/main/API.md#projen-awscdktypescriptapp) - AWS CDK app in TypeScript.
* [awscdk-construct](https://github.com/projen/projen/blob/main/API.md#projen-awscdkconstructlibrary) - AWS CDK construct library project.
* [cdk8s-app-ts](https://github.com/projen/projen/blob/main/API.md#projen-cdk8stypescriptapp) - CDK8s app in TypeScript.
Expand Down
93 changes: 20 additions & 73 deletions src/awscdk-app-ts.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
import * as path from 'path';
import * as fs from 'fs-extra';
import * as semver from 'semver';
import { CdkConfig, CdkConfigCommonOptions } from './awscdk/cdk-config';
import { CdkTasks } from './awscdk/cdk-tasks';
import { Component } from './component';
import { JsonFile } from './json';
import { TypeScriptAppProject, TypeScriptProjectOptions } from './typescript';

export enum CdkApprovalLevel {
/**
* Approval is never required
*/
NEVER = 'never',
/**
* Requires approval on any IAM or security-group-related change
*/
ANY_CHANGE = 'any-change',
/**
* Requires approval when IAM statements or traffic rules are added; removals don't require approval
*/
BROADENING = 'broadening',
}
export interface AwsCdkTypeScriptAppOptions extends TypeScriptProjectOptions {
export interface AwsCdkTypeScriptAppOptions extends TypeScriptProjectOptions, CdkConfigCommonOptions {
/**
* AWS CDK version to use.
*
Expand All @@ -44,27 +31,13 @@ export interface AwsCdkTypeScriptAppOptions extends TypeScriptProjectOptions {
*/
readonly cdkDependencies?: string[];

/**
* Additional context to include in `cdk.json`.
*/
readonly context?: { [key: string]: string };

/**
* The CDK app's entrypoint (relative to the source directory, which is
* "src" by default).
*
* @default "main.ts"
*/
readonly appEntrypoint?: string;

/**
* To protect you against unintended changes that affect your security posture,
* the AWS CDK Toolkit prompts you to approve security-related changes before deploying them.
*
* @default CdkApprovalLevel.BROADENING
*/
readonly requireApproval?: CdkApprovalLevel;

}

/**
Expand All @@ -79,14 +52,19 @@ export class AwsCdkTypeScriptApp extends TypeScriptAppProject {
public readonly cdkVersion: string;

/**
* Contents of `cdk.json`.
* The CDK app entrypoint
*/
public readonly cdkConfig: any;
public readonly appEntrypoint: string;

/**
* The CDK app entrypoint
* Common CDK tasks.
*/
public readonly appEntrypoint: string;
public readonly cdkTasks: CdkTasks;

/**
* cdk.json configuration.
*/
public readonly cdkConfig: CdkConfig;

constructor(options: AwsCdkTypeScriptAppOptions) {
super({
Expand Down Expand Up @@ -126,63 +104,32 @@ export class AwsCdkTypeScriptApp extends TypeScriptAppProject {

this.addCdkDependency(...options.cdkDependencies ?? []);

const synth = this.addTask('synth', {
description: 'Synthesizes your cdk app into cdk.out (part of "yarn build")',
exec: 'cdk synth',
});

this.addTask('deploy', {
description: 'Deploys your CDK app to the AWS cloud',
exec: 'cdk deploy',
});

this.addTask('destroy', {
description: 'Destroys your cdk app in the AWS cloud',
exec: 'cdk destroy',
});

this.addTask('diff', {
description: 'Diffs the currently deployed app against your code',
exec: 'cdk diff',
});
this.cdkTasks = new CdkTasks(this);

// no compile step because we do all of it in typescript directly
this.compileTask.reset();

this.removeScript('watch'); // because we use ts-node

// add synth to the build
this.buildTask.spawn(synth);
this.buildTask.spawn(this.cdkTasks.synth);

this.cdkConfig = {
app: `npx ts-node --prefer-ts-exts ${path.posix.join(this.srcdir, this.appEntrypoint)}`,
};

if (options.context) {
this.cdkConfig.context = { ...options.context };
}

if (options.requireApproval) {
this.cdkConfig.requireApproval = options.requireApproval;
}
this.cdkConfig = new CdkConfig(this, {
app: `npx ts-node --prefer-ts-exts ${path.posix.join(this.srcdir, this.appEntrypoint)}`,
...options,
});

this.gitignore.exclude('cdk.out/');
this.gitignore.exclude('.cdk.staging/');
this.gitignore.exclude('.parcel-cache/');

this.npmignore?.exclude('cdk.out/');
this.npmignore?.exclude(`${this.cdkConfig.cdkout}/`);
this.npmignore?.exclude('.cdk.staging/');

if (this.tsconfig) {
this.tsconfig.exclude.push('cdk.out');
this.tsconfig.exclude.push(this.cdkConfig.cdkout);
}

this.addDevDeps('ts-node@^9');

new JsonFile(this, 'cdk.json', {
obj: this.cdkConfig,
});

if (options.sampleCode ?? true) {
new SampleCode(this, cdkMajorVersion);
}
Expand Down
111 changes: 111 additions & 0 deletions src/awscdk/cdk-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { Component } from '../component';
import { JsonFile } from '../json';
import { Project } from '../project';
import { FEATURE_FLAGS } from './internal';

/**
* Common options for `cdk.json`.
*/
export interface CdkConfigCommonOptions {
/**
* Additional context to include in `cdk.json`.
*
* @default - no additional context
*/
readonly context?: { [key: string]: string };

/**
* Include all feature flags in cdk.json
*
* @default true
*/
readonly featureFlags?: boolean;

/**
* To protect you against unintended changes that affect your security posture,
* the AWS CDK Toolkit prompts you to approve security-related changes before deploying them.
*
* @default ApprovalLevel.BROADENING
*/
readonly requireApproval?: ApprovalLevel;

/**
* cdk.out directory.
*
* @default "cdk.out"
*/
readonly cdkout?: string;
}

/**
* Options for `CdkJson`.
*/
export interface CdkConfigOptions extends CdkConfigCommonOptions {
/**
* The command line to execute in order to synthesize the CDK application
* (language specific).
*/
readonly app: string;
}

/**
* Represents cdk.json file.
*/
export class CdkConfig extends Component {

/**
* Represents the JSON file.
*/
public readonly json: JsonFile;

/**
* Name of the cdk.out directory.
*/
public readonly cdkout: string;

constructor(project: Project, options: CdkConfigOptions) {
super(project);

this.cdkout = options.cdkout ?? 'cdk.out';

const context: Record<string, any> = { ...options.context };
const fflags = options.featureFlags ?? true;
if (fflags) {
for (const flag of FEATURE_FLAGS) {
context[flag] = true;
}
}

this.json = new JsonFile(project, 'cdk.json', {
omitEmpty: true,
obj: {
app: options.app,
context: context,
requireApproval: options.requireApproval,
output: this.cdkout,
},
});

project.gitignore.exclude(`/${this.cdkout}/`);
project.gitignore.exclude('.cdk.staging/');
}
}

/**
* Which approval is required when deploying CDK apps.
*/
export enum ApprovalLevel {
/**
* Approval is never required
*/
NEVER = 'never',
/**
* Requires approval on any IAM or security-group-related change
*/
ANY_CHANGE = 'any-change',
/**
* Requires approval when IAM statements or traffic rules are added; removals don't require approval
*/
BROADENING = 'broadening',
}

52 changes: 52 additions & 0 deletions src/awscdk/cdk-tasks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Component } from '../component';
import { Project } from '../project';
import { Task } from '../tasks';

/**
* Adds standard AWS CDK tasks to your project.
*/
export class CdkTasks extends Component {
/**
* Synthesizes your app.
*/
public readonly synth: Task;

/**
* Deploys your app.
*/
public readonly deploy: Task;

/**
* Destroys all the stacks.
*/
public readonly destroy: Task;

/**
* Diff against production.
*/
public readonly diff: Task;

constructor(project: Project) {
super(project);

this.synth = project.addTask('synth', {
description: 'Synthesizes your cdk app into cdk.out (part of "yarn build")',
exec: 'cdk synth',
});

this.deploy = project.addTask('deploy', {
description: 'Deploys your CDK app to the AWS cloud',
exec: 'cdk deploy',
});

this.destroy = project.addTask('destroy', {
description: 'Destroys your cdk app in the AWS cloud',
exec: 'cdk destroy',
});

this.diff = project.addTask('diff', {
description: 'Diffs the currently deployed app against your code',
exec: 'cdk diff',
});
}
}
3 changes: 3 additions & 0 deletions src/awscdk/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './java-app';
export * from './cdk-config';
export * from './cdk-tasks';
18 changes: 18 additions & 0 deletions src/awscdk/internal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Feature flags as of v1.130.0
*/
export const FEATURE_FLAGS = [
'aws-cdk:enableDiffNoFail',
'@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId',
'@aws-cdk/core:enableStackNameDuplicates',
'@aws-cdk/core:stackRelativeExports',
'@aws-cdk/aws-ecr-assets:dockerIgnoreSupport',
'@aws-cdk/aws-secretsmanager:parseOwnedSecretName',
'@aws-cdk/aws-kms:defaultKeyPolicies',
'@aws-cdk/aws-s3:grantWriteWithoutAcl',
'@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount',
'@aws-cdk/aws-rds:lowercaseDbIdentifier',
'@aws-cdk/aws-efs:defaultEncryptionAtRest',
'@aws-cdk/aws-lambda:recognizeVersionProps',
'@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021',
];
Loading

0 comments on commit b7753ec

Please sign in to comment.