From 7971a6dece9bf0dcb02576fd20979db0b4c8e28f Mon Sep 17 00:00:00 2001 From: wulfmann Date: Thu, 12 Nov 2020 15:49:51 +0000 Subject: [PATCH 1/8] update tests and add log config --- .../@aws-cdk/aws-codebuild/lib/project.ts | 110 ++++++++++++++++++ packages/@aws-cdk/aws-codebuild/package.json | 2 + .../aws-codebuild/test/test.project.ts | 67 +++++++++++ 3 files changed, 179 insertions(+) diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 8bfc8f38e09cf..e930a39897c9e 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -5,6 +5,7 @@ import { DockerImageAsset, DockerImageAssetProps } from '@aws-cdk/aws-ecr-assets import * as events from '@aws-cdk/aws-events'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; +import * as logs from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import { Aws, Duration, IResource, Lazy, Names, PhysicalName, Resource, Stack } from '@aws-cdk/core'; @@ -396,6 +397,76 @@ abstract class ProjectBase extends Resource implements IProject { } } +export enum LogStatus { + ENABLED='ENABLED', + DISABLED='DISABLED' +} + +/** + * Information about logs built to an S3 bucket for a build project. + */ +export interface S3LogsConfig { + /** + * Encrypt the S3 build log output + * @default true + */ + readonly encrypted?: boolean; + + /** + * The S3 Bucket to send logs to + */ + readonly bucket: s3.IBucket; + + /** + * The path prefix for S3 logs + */ + readonly prefix?: string; + + /** + * The current status of the logs in Amazon CloudWatch Logs for a build project + * @default ENABLED + */ + readonly status?: LogStatus; +} + +/** + * Information about logs built to an S3 bucket for a build project. + */ +export interface CloudwatchLogsConfig { + /** + * The S3 Bucket to send logs to + */ + readonly logGroup: logs.ILogGroup; + + /** + * The prefix of the stream name of the Amazon CloudWatch Logs + */ + readonly prefix?: string; + + /** + * The current status of the logs in Amazon CloudWatch Logs for a build project + * @default ENABLED + */ + readonly status?: LogStatus; +} + +/** + * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. + */ +export interface LogsConfig { + /** + * Information about logs built to an S3 bucket for a build project. + * @default - disabled + */ + readonly s3?: S3LogsConfig; + + /** + * Information about Amazon CloudWatch Logs for a build project. + * @default - enabled + */ + readonly cloudwatch?: CloudwatchLogsConfig; +} + export interface CommonProjectProps { /** * A description of the project. Use the description to identify the purpose @@ -538,6 +609,12 @@ export interface CommonProjectProps { * @see https://docs.aws.amazon.com/codebuild/latest/userguide/test-report-group-naming.html */ readonly grantReportGroupPermissions?: boolean; + + /** + * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. + * @default - no log configuration is set + */ + readonly logsConfig?: LogsConfig; } export interface ProjectProps extends CommonProjectProps { @@ -771,6 +848,7 @@ export class Project extends ProjectBase { triggers: sourceConfig.buildTriggers, sourceVersion: sourceConfig.sourceVersion, vpcConfig: this.configureVpc(props), + logsConfig: props.logsConfig && this.renderLogs(props), }); this.addVpcRequiredPermissions(props, resource); @@ -1036,6 +1114,38 @@ export class Project extends ProjectBase { }; } + private renderLogs(props: ProjectProps): CfnProject.LogsConfigProperty { + let s3Config: CfnProject.S3LogsConfigProperty|undefined; + let cloudwatchConfig: CfnProject.CloudWatchLogsConfigProperty|undefined; + + if (props.logsConfig?.s3) { + const s3Logs = props.logsConfig.s3; + s3Config = { + status: s3Logs.status || LogStatus.DISABLED, + location: `${s3Logs.bucket.bucketName}${s3Logs.prefix}`, + encryptionDisabled: s3Logs.encrypted || true, + }; + } else { + s3Config = undefined; + } + + if (props.logsConfig?.cloudwatch) { + const cloudWatchLogs = props.logsConfig.cloudwatch; + cloudwatchConfig = { + status: cloudWatchLogs.status || LogStatus.DISABLED, + groupName: cloudWatchLogs.logGroup.logGroupName, + streamName: cloudWatchLogs.prefix, + }; + } else { + cloudwatchConfig = undefined; + } + + return { + s3Logs: s3Config, + cloudWatchLogs: cloudwatchConfig, + }; + } + private addVpcRequiredPermissions(props: ProjectProps, project: CfnProject): void { if (!props.vpc || !this.role) { return; diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index fd8384c9da842..d67115b901423 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -96,6 +96,7 @@ "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", "@aws-cdk/aws-secretsmanager": "0.0.0", @@ -113,6 +114,7 @@ "@aws-cdk/aws-ecr-assets": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index f892f8b30eac2..8a48a825fe825 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -1,6 +1,7 @@ import { countResources, expect, haveResource, haveResourceLike, objectLike, not, ResourcePart } from '@aws-cdk/assert'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; +import * as logs from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import * as cdk from '@aws-cdk/core'; @@ -600,5 +601,71 @@ export = { test.done(); }, + + 'logs config - cloudwatch'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const logGroup = logs.LogGroup.fromLogGroupName(stack, 'LogGroup', 'MyLogGroupName'); + + // WHEN + new codebuild.Project(stack, 'Project', { + source: codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'Bucket'), + path: 'path', + }), + logsConfig: { + cloudwatch: { + logGroup, + prefix: '/my-logs', + }, + }, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { + LogsConfig: objectLike({ + S3LogsConfig: { + GroupName: 'MyLogGroup', + StreamName: '/my-logs', + Status: 'ENABLED', + }, + }), + })); + + test.done(); + }, + + 'logs config - s3'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const bucket = s3.Bucket.fromBucketName(stack, 'Bucket', 'MyBucketName'); + + // WHEN + new codebuild.Project(stack, 'Project', { + source: codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'Bucket'), + path: 'path', + }), + logsConfig: { + s3: { + bucket, + prefix: '/my-logs', + }, + }, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { + LogsConfig: objectLike({ + S3LogsConfig: { + Location: 'MyBucketName/my-logs', + Status: 'ENABLED', + Encrypted: true, + }, + }), + })); + + test.done(); + }, }, }; From 4abf28f2179d98232116573ebc5572a33611c583 Mon Sep 17 00:00:00 2001 From: wulfmann Date: Thu, 12 Nov 2020 16:04:11 +0000 Subject: [PATCH 2/8] fix linting issues, update tests, fix docs --- .../@aws-cdk/aws-codebuild/lib/project.ts | 19 ++++++++++++++++--- .../aws-codebuild/test/test.project.ts | 12 ++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index e930a39897c9e..911926aa6398f 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -397,8 +397,18 @@ abstract class ProjectBase extends Resource implements IProject { } } +/** + * Statuses for Log Configurations + */ export enum LogStatus { + /** + * Enables the log configuration + */ ENABLED='ENABLED', + + /** + * Disables the log configuration + */ DISABLED='DISABLED' } @@ -419,6 +429,7 @@ export interface S3LogsConfig { /** * The path prefix for S3 logs + * @default - no prefix */ readonly prefix?: string; @@ -440,6 +451,7 @@ export interface CloudwatchLogsConfig { /** * The prefix of the stream name of the Amazon CloudWatch Logs + * @default - no prefix */ readonly prefix?: string; @@ -1120,10 +1132,11 @@ export class Project extends ProjectBase { if (props.logsConfig?.s3) { const s3Logs = props.logsConfig.s3; + s3Config = { - status: s3Logs.status || LogStatus.DISABLED, + status: s3Logs.status || LogStatus.ENABLED, location: `${s3Logs.bucket.bucketName}${s3Logs.prefix}`, - encryptionDisabled: s3Logs.encrypted || true, + encryptionDisabled: s3Logs.encrypted ?? false, }; } else { s3Config = undefined; @@ -1132,7 +1145,7 @@ export class Project extends ProjectBase { if (props.logsConfig?.cloudwatch) { const cloudWatchLogs = props.logsConfig.cloudwatch; cloudwatchConfig = { - status: cloudWatchLogs.status || LogStatus.DISABLED, + status: cloudWatchLogs.status || LogStatus.ENABLED, groupName: cloudWatchLogs.logGroup.logGroupName, streamName: cloudWatchLogs.prefix, }; diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index 8a48a825fe825..772a49d7bd545 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -624,10 +624,10 @@ export = { // THEN expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { LogsConfig: objectLike({ - S3LogsConfig: { - GroupName: 'MyLogGroup', - StreamName: '/my-logs', + CloudWatchLogs: { + GroupName: 'MyLogGroupName', Status: 'ENABLED', + StreamName: '/my-logs', }, }), })); @@ -638,7 +638,7 @@ export = { 'logs config - s3'(test: Test) { // GIVEN const stack = new cdk.Stack(); - const bucket = s3.Bucket.fromBucketName(stack, 'Bucket', 'MyBucketName'); + const bucket = s3.Bucket.fromBucketName(stack, 'LogBucket', 'MyBucketName'); // WHEN new codebuild.Project(stack, 'Project', { @@ -657,10 +657,10 @@ export = { // THEN expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { LogsConfig: objectLike({ - S3LogsConfig: { + S3Logs: { + EncryptionDisabled: false, Location: 'MyBucketName/my-logs', Status: 'ENABLED', - Encrypted: true, }, }), })); From 166f9eab7aaeb3072d7ec8ec0b30a556393471f6 Mon Sep 17 00:00:00 2001 From: wulfmann Date: Thu, 12 Nov 2020 16:11:24 +0000 Subject: [PATCH 3/8] update readme --- packages/@aws-cdk/aws-codebuild/README.md | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index c51b263279e34..2103b28d7ba0f 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -305,6 +305,38 @@ new codebuild.Project(this, 'Project', { }) ``` +## Logs + +CodeBuild lets you specify an S3 Bucket, CloudWatch Log Group or both to receive logs from your projects. + +By default, logs will go to cloudwatch. + +### CloudWatch Logs Example + +```typescript +new codebuild.Project(this, 'Project', { + logsConfig: { + cloudwatch: { + logGroup: new cloudwatch.LogGroup(this, `MyLogGroup`), + } + }, + ... +}) +``` + +### S3 Logs Example + +```typescript +new codebuild.Project(this, 'Project', { + logsConfig: { + s3: { + bucket: new s3.Bucket(this, `LogBucket`) + } + }, + ... +}) +``` + ## Credentials CodeBuild allows you to store credentials used when communicating with various sources, From d80655ba52bfe933d4f385b263b974eb087b8480 Mon Sep 17 00:00:00 2001 From: wulfmann Date: Tue, 17 Nov 2020 13:34:41 +0000 Subject: [PATCH 4/8] add a new test, move interfaces to new file, remove enum and add enabled prop --- packages/@aws-cdk/aws-codebuild/lib/index.ts | 1 + .../aws-codebuild/lib/project-logs.ts | 69 +++++++++++++ .../@aws-cdk/aws-codebuild/lib/project.ts | 97 +++---------------- .../aws-codebuild/test/test.project.ts | 43 ++++++++ 4 files changed, 125 insertions(+), 85 deletions(-) create mode 100644 packages/@aws-cdk/aws-codebuild/lib/project-logs.ts diff --git a/packages/@aws-cdk/aws-codebuild/lib/index.ts b/packages/@aws-cdk/aws-codebuild/lib/index.ts index d1d0907ec734d..96731b2130043 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/index.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/index.ts @@ -1,6 +1,7 @@ export * from './events'; export * from './pipeline-project'; export * from './project'; +export * from './project-logs'; export * from './report-group'; export * from './source'; export * from './source-credentials'; diff --git a/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts b/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts new file mode 100644 index 0000000000000..e10e9118cede2 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts @@ -0,0 +1,69 @@ +import * as logs from '@aws-cdk/aws-logs'; +import * as s3 from '@aws-cdk/aws-s3'; + +/** + * Information about logs built to an S3 bucket for a build project. + */ +export interface S3LogsConfig { + /** + * Encrypt the S3 build log output + * @default true + */ + readonly encrypted?: boolean; + + /** + * The S3 Bucket to send logs to + */ + readonly bucket: s3.IBucket; + + /** + * The path prefix for S3 logs + * @default - no prefix + */ + readonly prefix?: string; + + /** + * The current status of the logs in Amazon CloudWatch Logs for a build project + * @default true + */ + readonly enabled?: boolean; +} + +/** + * Information about logs built to a Cloudwatch Log Group for a build project. + */ +export interface CloudwatchLogsConfig { + /** + * The Log Group to send logs to + */ + readonly logGroup: logs.ILogGroup; + + /** + * The prefix of the stream name of the Amazon CloudWatch Logs + * @default - no prefix + */ + readonly prefix?: string; + + /** + * The current status of the logs in Amazon CloudWatch Logs for a build project + * @default true + */ + readonly enabled?: boolean; +} + +/** + * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. + */ +export interface LogsConfig { + /** + * Information about logs built to an S3 bucket for a build project. + * @default - disabled + */ + readonly s3?: S3LogsConfig; + + /** + * Information about Amazon CloudWatch Logs for a build project. + * @default - enabled + */ + readonly cloudwatch?: CloudwatchLogsConfig; +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 911926aa6398f..6a5971e2fcd6e 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -5,7 +5,6 @@ import { DockerImageAsset, DockerImageAssetProps } from '@aws-cdk/aws-ecr-assets import * as events from '@aws-cdk/aws-events'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import * as logs from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import { Aws, Duration, IResource, Lazy, Names, PhysicalName, Resource, Stack } from '@aws-cdk/core'; @@ -19,6 +18,7 @@ import { IFileSystemLocation } from './file-location'; import { NoArtifacts } from './no-artifacts'; import { NoSource } from './no-source'; import { runScriptLinuxBuildSpec, S3_BUCKET_ENV, S3_KEY_ENV } from './private/run-script-linux-build-spec'; +import { LogsConfig } from './project-logs'; import { renderReportGroupArn } from './report-group-utils'; import { ISource } from './source'; import { CODEPIPELINE_SOURCE_ARTIFACTS_TYPE, NO_SOURCE_TYPE } from './source-types'; @@ -397,88 +397,6 @@ abstract class ProjectBase extends Resource implements IProject { } } -/** - * Statuses for Log Configurations - */ -export enum LogStatus { - /** - * Enables the log configuration - */ - ENABLED='ENABLED', - - /** - * Disables the log configuration - */ - DISABLED='DISABLED' -} - -/** - * Information about logs built to an S3 bucket for a build project. - */ -export interface S3LogsConfig { - /** - * Encrypt the S3 build log output - * @default true - */ - readonly encrypted?: boolean; - - /** - * The S3 Bucket to send logs to - */ - readonly bucket: s3.IBucket; - - /** - * The path prefix for S3 logs - * @default - no prefix - */ - readonly prefix?: string; - - /** - * The current status of the logs in Amazon CloudWatch Logs for a build project - * @default ENABLED - */ - readonly status?: LogStatus; -} - -/** - * Information about logs built to an S3 bucket for a build project. - */ -export interface CloudwatchLogsConfig { - /** - * The S3 Bucket to send logs to - */ - readonly logGroup: logs.ILogGroup; - - /** - * The prefix of the stream name of the Amazon CloudWatch Logs - * @default - no prefix - */ - readonly prefix?: string; - - /** - * The current status of the logs in Amazon CloudWatch Logs for a build project - * @default ENABLED - */ - readonly status?: LogStatus; -} - -/** - * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. - */ -export interface LogsConfig { - /** - * Information about logs built to an S3 bucket for a build project. - * @default - disabled - */ - readonly s3?: S3LogsConfig; - - /** - * Information about Amazon CloudWatch Logs for a build project. - * @default - enabled - */ - readonly cloudwatch?: CloudwatchLogsConfig; -} - export interface CommonProjectProps { /** * A description of the project. Use the description to identify the purpose @@ -1133,8 +1051,13 @@ export class Project extends ProjectBase { if (props.logsConfig?.s3) { const s3Logs = props.logsConfig.s3; + let status = 'ENABLED'; + if ('enabled' in s3Logs) { + status = s3Logs.enabled ? 'ENABLED' : 'DISABLED'; + } + s3Config = { - status: s3Logs.status || LogStatus.ENABLED, + status, location: `${s3Logs.bucket.bucketName}${s3Logs.prefix}`, encryptionDisabled: s3Logs.encrypted ?? false, }; @@ -1144,8 +1067,12 @@ export class Project extends ProjectBase { if (props.logsConfig?.cloudwatch) { const cloudWatchLogs = props.logsConfig.cloudwatch; + let status = 'ENABLED'; + if ('enabled' in cloudWatchLogs) { + status = cloudWatchLogs.enabled ? 'ENABLED' : 'DISABLED'; + } cloudwatchConfig = { - status: cloudWatchLogs.status || LogStatus.ENABLED, + status, groupName: cloudWatchLogs.logGroup.logGroupName, streamName: cloudWatchLogs.prefix, }; diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index 772a49d7bd545..9bb1292a17a94 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -667,5 +667,48 @@ export = { test.done(); }, + + 'logs config - cloudwatch and s3'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const bucket = s3.Bucket.fromBucketName(stack, 'LogBucket2', 'MyBucketName'); + const logGroup = logs.LogGroup.fromLogGroupName(stack, 'LogGroup2', 'MyLogGroupName'); + + // WHEN + new codebuild.Project(stack, 'Project', { + source: codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'Bucket'), + path: 'path', + }), + logsConfig: { + cloudwatch: { + logGroup, + prefix: '/my-logs', + }, + s3: { + bucket, + prefix: '/my-logs', + }, + }, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { + LogsConfig: objectLike({ + CloudWatchLogs: { + GroupName: 'MyLogGroupName', + Status: 'ENABLED', + StreamName: '/my-logs', + }, + S3Logs: { + EncryptionDisabled: false, + Location: 'MyBucketName/my-logs', + Status: 'ENABLED', + }, + }), + })); + + test.done(); + }, }, }; From eefc8ddc03144b987a812caa505d92c55c349319 Mon Sep 17 00:00:00 2001 From: wulfmann Date: Wed, 18 Nov 2020 13:10:43 +0000 Subject: [PATCH 5/8] refactor some names, add another test, update readme --- packages/@aws-cdk/aws-codebuild/README.md | 4 +-- .../aws-codebuild/lib/project-logs.ts | 21 +++++++---- .../@aws-cdk/aws-codebuild/lib/project.ts | 21 ++++++----- .../aws-codebuild/test/test.project.ts | 35 +++++++++++++++++-- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index 2103b28d7ba0f..c4a196b4d384f 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -315,7 +315,7 @@ By default, logs will go to cloudwatch. ```typescript new codebuild.Project(this, 'Project', { - logsConfig: { + logging: { cloudwatch: { logGroup: new cloudwatch.LogGroup(this, `MyLogGroup`), } @@ -328,7 +328,7 @@ new codebuild.Project(this, 'Project', { ```typescript new codebuild.Project(this, 'Project', { - logsConfig: { + logging: { s3: { bucket: new s3.Bucket(this, `LogBucket`) } diff --git a/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts b/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts index e10e9118cede2..1f894c7c27ff6 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts @@ -4,9 +4,10 @@ import * as s3 from '@aws-cdk/aws-s3'; /** * Information about logs built to an S3 bucket for a build project. */ -export interface S3LogsConfig { +export interface S3LogsOptions { /** * Encrypt the S3 build log output + * * @default true */ readonly encrypted?: boolean; @@ -18,12 +19,14 @@ export interface S3LogsConfig { /** * The path prefix for S3 logs + * * @default - no prefix */ readonly prefix?: string; /** * The current status of the logs in Amazon CloudWatch Logs for a build project + * * @default true */ readonly enabled?: boolean; @@ -32,20 +35,24 @@ export interface S3LogsConfig { /** * Information about logs built to a Cloudwatch Log Group for a build project. */ -export interface CloudwatchLogsConfig { +export interface CloudwatchLogsOptions { /** * The Log Group to send logs to + * + * @default - no log group specified */ - readonly logGroup: logs.ILogGroup; + readonly logGroup?: logs.ILogGroup; /** * The prefix of the stream name of the Amazon CloudWatch Logs + * * @default - no prefix */ readonly prefix?: string; /** * The current status of the logs in Amazon CloudWatch Logs for a build project + * * @default true */ readonly enabled?: boolean; @@ -54,16 +61,18 @@ export interface CloudwatchLogsConfig { /** * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. */ -export interface LogsConfig { +export interface LogsOptions { /** * Information about logs built to an S3 bucket for a build project. + * * @default - disabled */ - readonly s3?: S3LogsConfig; + readonly s3?: S3LogsOptions; /** * Information about Amazon CloudWatch Logs for a build project. + * * @default - enabled */ - readonly cloudwatch?: CloudwatchLogsConfig; + readonly cloudwatch?: CloudwatchLogsOptions; } diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 6a5971e2fcd6e..e18fca146ab82 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -18,7 +18,7 @@ import { IFileSystemLocation } from './file-location'; import { NoArtifacts } from './no-artifacts'; import { NoSource } from './no-source'; import { runScriptLinuxBuildSpec, S3_BUCKET_ENV, S3_KEY_ENV } from './private/run-script-linux-build-spec'; -import { LogsConfig } from './project-logs'; +import { LogsOptions } from './project-logs'; import { renderReportGroupArn } from './report-group-utils'; import { ISource } from './source'; import { CODEPIPELINE_SOURCE_ARTIFACTS_TYPE, NO_SOURCE_TYPE } from './source-types'; @@ -544,7 +544,7 @@ export interface CommonProjectProps { * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. * @default - no log configuration is set */ - readonly logsConfig?: LogsConfig; + readonly logging?: LogsOptions; } export interface ProjectProps extends CommonProjectProps { @@ -778,7 +778,7 @@ export class Project extends ProjectBase { triggers: sourceConfig.buildTriggers, sourceVersion: sourceConfig.sourceVersion, vpcConfig: this.configureVpc(props), - logsConfig: props.logsConfig && this.renderLogs(props), + logsConfig: props.logging && this.renderLogs(props), }); this.addVpcRequiredPermissions(props, resource); @@ -1048,8 +1048,8 @@ export class Project extends ProjectBase { let s3Config: CfnProject.S3LogsConfigProperty|undefined; let cloudwatchConfig: CfnProject.CloudWatchLogsConfigProperty|undefined; - if (props.logsConfig?.s3) { - const s3Logs = props.logsConfig.s3; + if (props.logging?.s3) { + const s3Logs = props.logging.s3; let status = 'ENABLED'; if ('enabled' in s3Logs) { @@ -1065,15 +1065,20 @@ export class Project extends ProjectBase { s3Config = undefined; } - if (props.logsConfig?.cloudwatch) { - const cloudWatchLogs = props.logsConfig.cloudwatch; + if (props.logging?.cloudwatch) { + const cloudWatchLogs = props.logging.cloudwatch; let status = 'ENABLED'; if ('enabled' in cloudWatchLogs) { status = cloudWatchLogs.enabled ? 'ENABLED' : 'DISABLED'; } + + if (status === 'ENABLED' && !(cloudWatchLogs.logGroup)) { + throw new Error('A log group is required if cloudwatch logging is enabled'); + } + cloudwatchConfig = { status, - groupName: cloudWatchLogs.logGroup.logGroupName, + groupName: cloudWatchLogs.logGroup?.logGroupName, streamName: cloudWatchLogs.prefix, }; } else { diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index 9bb1292a17a94..0994d37a43b57 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -613,7 +613,7 @@ export = { bucket: new s3.Bucket(stack, 'Bucket'), path: 'path', }), - logsConfig: { + logging: { cloudwatch: { logGroup, prefix: '/my-logs', @@ -635,6 +635,35 @@ export = { test.done(); }, + 'logs config - cloudwatch disabled'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + new codebuild.Project(stack, 'Project', { + source: codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'Bucket'), + path: 'path', + }), + logging: { + cloudwatch: { + enabled: false, + }, + }, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { + LogsConfig: objectLike({ + CloudWatchLogs: { + Status: 'DISABLED', + }, + }), + })); + + test.done(); + }, + 'logs config - s3'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -646,7 +675,7 @@ export = { bucket: new s3.Bucket(stack, 'Bucket'), path: 'path', }), - logsConfig: { + logging: { s3: { bucket, prefix: '/my-logs', @@ -680,7 +709,7 @@ export = { bucket: new s3.Bucket(stack, 'Bucket'), path: 'path', }), - logsConfig: { + logging: { cloudwatch: { logGroup, prefix: '/my-logs', From 308dc89b657f81c4966ea03a7c00ec4ae3cdb96e Mon Sep 17 00:00:00 2001 From: wulfmann Date: Wed, 18 Nov 2020 13:12:21 +0000 Subject: [PATCH 6/8] fix a couple missed things --- packages/@aws-cdk/aws-codebuild/lib/project.ts | 1 + packages/@aws-cdk/aws-codebuild/package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index e18fca146ab82..9b01649363cc0 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -542,6 +542,7 @@ export interface CommonProjectProps { /** * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. + * * @default - no log configuration is set */ readonly logging?: LogsOptions; diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index 0326ec5eedb09..dc2e5ae89de99 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -114,8 +114,8 @@ "@aws-cdk/aws-ecr-assets": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", - "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", "@aws-cdk/aws-secretsmanager": "0.0.0", From f1364993ae6b08cb2d45c1153e4f57bce9c05824 Mon Sep 17 00:00:00 2001 From: wulfmann Date: Thu, 19 Nov 2020 15:33:23 +0000 Subject: [PATCH 7/8] refactor logging names, update tests/readme, fix cloudwatch naming --- packages/@aws-cdk/aws-codebuild/README.md | 2 +- .../aws-codebuild/lib/project-logs.ts | 12 +++--- .../@aws-cdk/aws-codebuild/lib/project.ts | 43 ++++++++----------- .../aws-codebuild/test/test.project.ts | 14 +++--- 4 files changed, 30 insertions(+), 41 deletions(-) diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index c4a196b4d384f..8dc9d1db9f9ec 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -316,7 +316,7 @@ By default, logs will go to cloudwatch. ```typescript new codebuild.Project(this, 'Project', { logging: { - cloudwatch: { + cloudWatch: { logGroup: new cloudwatch.LogGroup(this, `MyLogGroup`), } }, diff --git a/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts b/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts index 1f894c7c27ff6..d2613462d6330 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project-logs.ts @@ -4,7 +4,7 @@ import * as s3 from '@aws-cdk/aws-s3'; /** * Information about logs built to an S3 bucket for a build project. */ -export interface S3LogsOptions { +export interface S3LoggingOptions { /** * Encrypt the S3 build log output * @@ -33,9 +33,9 @@ export interface S3LogsOptions { } /** - * Information about logs built to a Cloudwatch Log Group for a build project. + * Information about logs built to a CloudWatch Log Group for a build project. */ -export interface CloudwatchLogsOptions { +export interface CloudWatchLoggingOptions { /** * The Log Group to send logs to * @@ -61,18 +61,18 @@ export interface CloudwatchLogsOptions { /** * Information about logs for the build project. A project can create logs in Amazon CloudWatch Logs, an S3 bucket, or both. */ -export interface LogsOptions { +export interface LoggingOptions { /** * Information about logs built to an S3 bucket for a build project. * * @default - disabled */ - readonly s3?: S3LogsOptions; + readonly s3?: S3LoggingOptions; /** * Information about Amazon CloudWatch Logs for a build project. * * @default - enabled */ - readonly cloudwatch?: CloudwatchLogsOptions; + readonly cloudWatch?: CloudWatchLoggingOptions; } diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 9b01649363cc0..e80b973ddef04 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -18,7 +18,7 @@ import { IFileSystemLocation } from './file-location'; import { NoArtifacts } from './no-artifacts'; import { NoSource } from './no-source'; import { runScriptLinuxBuildSpec, S3_BUCKET_ENV, S3_KEY_ENV } from './private/run-script-linux-build-spec'; -import { LogsOptions } from './project-logs'; +import { LoggingOptions } from './project-logs'; import { renderReportGroupArn } from './report-group-utils'; import { ISource } from './source'; import { CODEPIPELINE_SOURCE_ARTIFACTS_TYPE, NO_SOURCE_TYPE } from './source-types'; @@ -545,7 +545,7 @@ export interface CommonProjectProps { * * @default - no log configuration is set */ - readonly logging?: LogsOptions; + readonly logging?: LoggingOptions; } export interface ProjectProps extends CommonProjectProps { @@ -779,7 +779,7 @@ export class Project extends ProjectBase { triggers: sourceConfig.buildTriggers, sourceVersion: sourceConfig.sourceVersion, vpcConfig: this.configureVpc(props), - logsConfig: props.logging && this.renderLogs(props), + logsConfig: this.renderLoggingConfiguration(props.logging), }); this.addVpcRequiredPermissions(props, resource); @@ -1045,36 +1045,29 @@ export class Project extends ProjectBase { }; } - private renderLogs(props: ProjectProps): CfnProject.LogsConfigProperty { - let s3Config: CfnProject.S3LogsConfigProperty|undefined; - let cloudwatchConfig: CfnProject.CloudWatchLogsConfigProperty|undefined; - - if (props.logging?.s3) { - const s3Logs = props.logging.s3; + private renderLoggingConfiguration(props: LoggingOptions | undefined): CfnProject.LogsConfigProperty | undefined { + if (props === undefined) { + return undefined; + }; - let status = 'ENABLED'; - if ('enabled' in s3Logs) { - status = s3Logs.enabled ? 'ENABLED' : 'DISABLED'; - } + let s3Config: CfnProject.S3LogsConfigProperty|undefined = undefined; + let cloudwatchConfig: CfnProject.CloudWatchLogsConfigProperty|undefined = undefined; + if (props.s3) { + const s3Logs = props.s3; s3Config = { - status, + status: (s3Logs.enabled ?? true) ? 'ENABLED' : 'DISABLED', location: `${s3Logs.bucket.bucketName}${s3Logs.prefix}`, - encryptionDisabled: s3Logs.encrypted ?? false, + encryptionDisabled: s3Logs.encrypted, }; - } else { - s3Config = undefined; } - if (props.logging?.cloudwatch) { - const cloudWatchLogs = props.logging.cloudwatch; - let status = 'ENABLED'; - if ('enabled' in cloudWatchLogs) { - status = cloudWatchLogs.enabled ? 'ENABLED' : 'DISABLED'; - } + if (props.cloudWatch) { + const cloudWatchLogs = props.cloudWatch; + const status = (cloudWatchLogs.enabled ?? true) ? 'ENABLED' : 'DISABLED'; if (status === 'ENABLED' && !(cloudWatchLogs.logGroup)) { - throw new Error('A log group is required if cloudwatch logging is enabled'); + throw new Error('Specifying a LogGroup is required if CloudWatch logging for CodeBuild is enabled'); } cloudwatchConfig = { @@ -1082,8 +1075,6 @@ export class Project extends ProjectBase { groupName: cloudWatchLogs.logGroup?.logGroupName, streamName: cloudWatchLogs.prefix, }; - } else { - cloudwatchConfig = undefined; } return { diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index 0994d37a43b57..bd6c2e100a0d2 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -602,7 +602,7 @@ export = { test.done(); }, - 'logs config - cloudwatch'(test: Test) { + 'logs config - cloudWatch'(test: Test) { // GIVEN const stack = new cdk.Stack(); const logGroup = logs.LogGroup.fromLogGroupName(stack, 'LogGroup', 'MyLogGroupName'); @@ -614,7 +614,7 @@ export = { path: 'path', }), logging: { - cloudwatch: { + cloudWatch: { logGroup, prefix: '/my-logs', }, @@ -635,7 +635,7 @@ export = { test.done(); }, - 'logs config - cloudwatch disabled'(test: Test) { + 'logs config - cloudWatch disabled'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -646,7 +646,7 @@ export = { path: 'path', }), logging: { - cloudwatch: { + cloudWatch: { enabled: false, }, }, @@ -687,7 +687,6 @@ export = { expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { LogsConfig: objectLike({ S3Logs: { - EncryptionDisabled: false, Location: 'MyBucketName/my-logs', Status: 'ENABLED', }, @@ -697,7 +696,7 @@ export = { test.done(); }, - 'logs config - cloudwatch and s3'(test: Test) { + 'logs config - cloudWatch and s3'(test: Test) { // GIVEN const stack = new cdk.Stack(); const bucket = s3.Bucket.fromBucketName(stack, 'LogBucket2', 'MyBucketName'); @@ -710,7 +709,7 @@ export = { path: 'path', }), logging: { - cloudwatch: { + cloudWatch: { logGroup, prefix: '/my-logs', }, @@ -730,7 +729,6 @@ export = { StreamName: '/my-logs', }, S3Logs: { - EncryptionDisabled: false, Location: 'MyBucketName/my-logs', Status: 'ENABLED', }, From cb023b05395ae193c459925cfad2eb48cde5b751 Mon Sep 17 00:00:00 2001 From: wulfmann Date: Thu, 19 Nov 2020 15:35:19 +0000 Subject: [PATCH 8/8] add separator to s3 location and update tests --- packages/@aws-cdk/aws-codebuild/lib/project.ts | 2 +- packages/@aws-cdk/aws-codebuild/test/test.project.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index e80b973ddef04..8973dc8f5ea04 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -1057,7 +1057,7 @@ export class Project extends ProjectBase { const s3Logs = props.s3; s3Config = { status: (s3Logs.enabled ?? true) ? 'ENABLED' : 'DISABLED', - location: `${s3Logs.bucket.bucketName}${s3Logs.prefix}`, + location: `${s3Logs.bucket.bucketName}/${s3Logs.prefix}`, encryptionDisabled: s3Logs.encrypted, }; } diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index bd6c2e100a0d2..439427588afdb 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -678,7 +678,7 @@ export = { logging: { s3: { bucket, - prefix: '/my-logs', + prefix: 'my-logs', }, }, }); @@ -715,7 +715,7 @@ export = { }, s3: { bucket, - prefix: '/my-logs', + prefix: 'my-logs', }, }, });