Skip to content

Commit

Permalink
Add option to disable CloudWatch log streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
leoherran-aws committed Feb 22, 2019
1 parent d8627d0 commit dfd9268
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 24 deletions.
14 changes: 11 additions & 3 deletions src/main/java/CloudWatchMonitor.java
Expand Up @@ -34,24 +34,33 @@ public class CloudWatchMonitor {
@Setter @Getter private LogsLocation logsLocation;
@Getter private List<String> latestLogs;
@Getter private Long lastPollTime;
private boolean cwlStreamingDisabled;

private static final int htmlMaxLineLength = 2000;
public static final String noLogsMessage = "No CloudWatch logs found for this build.";
public static final String streamingDisabledMessage = "CloudWatch logs streaming is disabled for this build.";
public static final String failedConfigurationLogsMessage = "CloudWatch configuration for this build is incorrect.";

public CloudWatchMonitor(AWSLogsClient client) {
public CloudWatchMonitor(AWSLogsClient client, boolean cwlStreamingDisabled) {
this.logsClient = client;
this.cwlStreamingDisabled = cwlStreamingDisabled;
if(!Validation.checkCloudWatchMonitorConfig(logsClient)) {
latestLogs = Arrays.asList(failedConfigurationLogsMessage);
return;
}
if(cwlStreamingDisabled) {
latestLogs = Arrays.asList(streamingDisabledMessage);
}
lastPollTime = 0L;
}

// Checks if the CloudWatch logs exist. If they do, retrieves/stores them in this.latestLogs.
// If the logs don't exist yet, sets this.latestLogs to an error message.
// Does nothing if CloudWatch logs streaming is disabled
public void pollForLogs(TaskListener listener) {
if(this.logsLocation != null && this.logsLocation.getGroupName() != null && this.logsLocation.getStreamName() != null) {
if(cwlStreamingDisabled) {
return;
} else if(this.logsLocation != null && this.logsLocation.getGroupName() != null && this.logsLocation.getStreamName() != null) {
this.latestLogs = new ArrayList();
GetLogEventsRequest logRequest = new GetLogEventsRequest()
.withStartTime(lastPollTime)
Expand All @@ -69,7 +78,6 @@ public void pollForLogs(TaskListener listener) {
latestLogs = Arrays.asList(noLogsMessage);
return;
}

}

private void getAndFormatLogs(List<OutputLogEvent> logs, TaskListener listener) {
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/CodeBuildAction.java
Expand Up @@ -168,10 +168,14 @@ public String getBuildStatus() {

public void updateLogs(List<String> newLogs) {
if(logs != null) {
if(logs.size() == 1 && logs.get(0).equals(CloudWatchMonitor.noLogsMessage)) { //no logs message already displayed
if(newLogs.size() > 0 && !newLogs.get(0).equals(CloudWatchMonitor.noLogsMessage)) {
logs = new ArrayList();
} else {
if(logs.size() == 1) {
if(logs.get(0).equals(CloudWatchMonitor.noLogsMessage)) {
if (newLogs.size() > 0 && !newLogs.get(0).equals(CloudWatchMonitor.noLogsMessage)) {
logs = new ArrayList();
} else {
return;
}
} else if(logs.get(0).equals(CloudWatchMonitor.streamingDisabledMessage)) {
return;
}
}
Expand Down
18 changes: 17 additions & 1 deletion src/main/java/CodeBuildStep.java
Expand Up @@ -86,6 +86,7 @@ public class CodeBuildStep extends AbstractStepImpl {
@Getter private String envParameters;
@Getter private String buildSpecFile;
@Getter private String buildTimeoutOverride;
@Getter private String cwlStreamingDisabled;

@DataBoundSetter
public void setCredentialsType(String credentialsType) {
Expand Down Expand Up @@ -307,6 +308,11 @@ public void setBuildTimeoutOverride(String buildTimeoutOverride) {
this.buildTimeoutOverride = buildTimeoutOverride;
}

@DataBoundSetter
public void setCwlStreamingDisabled(String cwlStreamingDisabled) {
this.cwlStreamingDisabled = cwlStreamingDisabled;
}

@Extension
public static final class DescriptorImpl extends AbstractStepDescriptorImpl {

Expand Down Expand Up @@ -528,6 +534,16 @@ public ListBoxModel doFillSseAlgorithmItems() {
return selections;
}

public ListBoxModel doFillCwlStreamingDisabledItems() {
final ListBoxModel selections = new ListBoxModel();

for(BooleanValue t: BooleanValue.values()) {
selections.add(t.toString());
}

return selections;
}

}

public static final class CodeBuildExecution extends AbstractSynchronousNonBlockingStepExecution<CodeBuildResult> {
Expand Down Expand Up @@ -565,7 +581,7 @@ protected CodeBuildResult run() throws Exception {
step.getImageOverride(), step.getComputeTypeOverride(), step.getCacheTypeOverride(), step.getCacheLocationOverride(),
step.getCloudWatchLogsStatusOverride(), step.getCloudWatchLogsGroupNameOverride(), step.getCloudWatchLogsStreamNameOverride(),
step.getS3LogsStatusOverride(), step.getS3LogsLocationOverride(), step.getCertificateOverride(), step.getServiceRoleOverride(),
step.getInsecureSslOverride(), step.getPrivilegedModeOverride()
step.getInsecureSslOverride(), step.getPrivilegedModeOverride(), step.getCwlStreamingDisabled()
).readResolve();
builder.perform(run, ws, launcher, listener, getContext());

Expand Down
20 changes: 18 additions & 2 deletions src/main/java/CodeBuilder.java
Expand Up @@ -92,6 +92,7 @@ public class CodeBuilder extends Builder implements SimpleBuildStep {
@Getter private String envParameters;
@Getter private String buildSpecFile;
@Getter private String buildTimeoutOverride;
@Getter private String cwlStreamingDisabled;

@Getter private final CodeBuildResult codeBuildResult;
private EnvVars envVars;
Expand Down Expand Up @@ -129,7 +130,7 @@ public CodeBuilder(String credentialsType, String credentialsId, String proxyHos
String sourceLocationOverride, String environmentTypeOverride, String imageOverride, String computeTypeOverride,
String cacheTypeOverride, String cacheLocationOverride, String cloudWatchLogsStatusOverride, String cloudWatchLogsGroupNameOverride, String cloudWatchLogsStreamNameOverride,
String s3LogsStatusOverride, String s3LogsLocationOverride, String certificateOverride, String serviceRoleOverride,
String insecureSslOverride, String privilegedModeOverride) {
String insecureSslOverride, String privilegedModeOverride, String cwlStreamingDisabled) {

this.credentialsType = Validation.sanitize(credentialsType);
this.credentialsId = Validation.sanitize(credentialsId);
Expand Down Expand Up @@ -175,6 +176,7 @@ public CodeBuilder(String credentialsType, String credentialsId, String proxyHos
this.buildTimeoutOverride = Validation.sanitize(buildTimeoutOverride);
this.insecureSslOverride = Validation.sanitize(insecureSslOverride);
this.privilegedModeOverride = Validation.sanitize(privilegedModeOverride);
this.cwlStreamingDisabled = Validation.sanitize(cwlStreamingDisabled);
this.codeBuildResult = new CodeBuildResult();
this.batchGetBuildsCalls = 0;
}
Expand Down Expand Up @@ -223,6 +225,7 @@ protected Object readResolve() {
buildTimeoutOverride = Validation.sanitize(buildTimeoutOverride);
insecureSslOverride = Validation.sanitize(insecureSslOverride);
privilegedModeOverride = Validation.sanitize(privilegedModeOverride);
cwlStreamingDisabled = Validation.sanitize(cwlStreamingDisabled);
return this;
}

Expand Down Expand Up @@ -428,7 +431,7 @@ public void perform(@Nonnull Run<?, ?> build, @Nonnull FilePath ws, @Nonnull Lau

currentBuild = buildsForId.get(0);
if(!haveInitializedAction) {
logMonitor = new CloudWatchMonitor(awsClientFactory.getCloudWatchLogsClient());
logMonitor = new CloudWatchMonitor(awsClientFactory.getCloudWatchLogsClient(), Boolean.parseBoolean(getParameterized(cwlStreamingDisabled)));
action = new CodeBuildAction(build);

//only need to set these once, the others will need to be updated below as the build progresses.
Expand Down Expand Up @@ -708,6 +711,9 @@ private void logStartBuildMessage(TaskListener listener, String sourceVersion) {
if(!serviceRoleOverride.isEmpty()) {
message.append("\n\t> service role: " + getParameterized(serviceRoleOverride));
}
if(!cwlStreamingDisabled.isEmpty()) {
message.append("\n\t> CloudWatch logs streaming disabled: " + getParameterized(cwlStreamingDisabled));
}
if(!buildSpecFile.isEmpty()) {
message.append("\n\t> build spec: \n" + getParameterized(buildSpecFile));
}
Expand Down Expand Up @@ -1128,6 +1134,16 @@ public ListBoxModel doFillSseAlgorithmItems() {
return selections;
}

public ListBoxModel doFillCwlStreamingDisabledItems() {
final ListBoxModel selections = new ListBoxModel();

for(BooleanValue t: BooleanValue.values()) {
selections.add(t.toString());
}

return selections;
}

public boolean isApplicable(Class<? extends AbstractProject> aClass) {
// Indicates that this builder can be used with all kinds of project types
return true;
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/CodeBuilder/config.jelly
Expand Up @@ -208,5 +208,9 @@
<f:textbox />
</f:entry>

<f:entry title="Disable CloudWatch Streaming" field="cwlStreamingDisabled" help="/plugin/aws-codebuild/help-cwlStreamingDisabled.html">
<f:select />
</f:entry>

</f:section>
</j:jelly>
17 changes: 17 additions & 0 deletions src/main/webapp/help-cwlStreamingDisabled.html
@@ -0,0 +1,17 @@
<!--
~ Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License.
~ A copy of the License is located at
~
~ http://aws.amazon.com/apache2.0/
~
~ or in the "license" file accompanying this file.
~ This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and limitations under the License.
-->

<div>
When set to true, prevents the plugin from downloading your build logs from CloudWatch and displaying them in the CodeBuild
dashboard and console log.
</div>
15 changes: 13 additions & 2 deletions src/test/java/CloudWatchMonitorTest.java
Expand Up @@ -28,6 +28,7 @@
import java.io.PrintStream;
import java.util.*;

import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Matchers.any;
Expand All @@ -54,7 +55,7 @@ public void setUp() {

@Test
public void testInvalidConfig() throws Exception {
CloudWatchMonitor c = new CloudWatchMonitor(null);
CloudWatchMonitor c = new CloudWatchMonitor(null, false);
assertLogsContainErrorMessage(c);
}

Expand Down Expand Up @@ -113,8 +114,18 @@ public void testFormatLogsTwoCalls() throws Exception {
assert(c.getLastPollTime() == 4L);
}

@Test
public void testCwlStreamingDisabled() throws Exception {
CloudWatchMonitor c = new CloudWatchMonitor(mockClient, true);
assertEquals(c.getLatestLogs().size(), 1);
assertEquals(c.getLatestLogs().get(0), CloudWatchMonitor.streamingDisabledMessage);
c.pollForLogs(listener);
assertEquals(c.getLatestLogs().size(), 1);
assertEquals(c.getLatestLogs().get(0), CloudWatchMonitor.streamingDisabledMessage);
}

private CloudWatchMonitor getMockCloudWatchMonitor() {
CloudWatchMonitor c = new CloudWatchMonitor(mockClient);
CloudWatchMonitor c = new CloudWatchMonitor(mockClient, false);
c.setLogsLocation(new LogsLocation().withGroupName(mockGroup).withStreamName(mockStream));
return c;
}
Expand Down
22 changes: 11 additions & 11 deletions src/test/java/CodeBuilderPerformTest.java
Expand Up @@ -53,7 +53,7 @@ public void testConfigAllNull() throws Exception {
null, null, null, null, null, null,
null, null, null, null, null,
null, null, null, null, null,
null, null, null, null);
null, null, null, null, null);

ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);
Expand All @@ -75,7 +75,7 @@ public void testConfigAllBlank() throws Exception {
"", "", "", "", "", "",
"", "", "", "", "",
"", "", "", "", "",
"", "", "", "");
"", "", "", "", "");

ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);
Expand All @@ -97,7 +97,7 @@ public void testNoProjectName() throws Exception {
"", "", "", "", "", "",
"", "", "", "", "",
"", "", "", "", "",
"", "", "", "");
"", "", "", "", "");

ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);
Expand All @@ -122,7 +122,7 @@ public void testNoSourceType() throws Exception {
"", "", "", "", "", "",
"", "", "", "", "",
"", "", "", "", "",
"", "", "", "");
"", "", "", "", "");

ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);
Expand Down Expand Up @@ -199,7 +199,7 @@ public void testComputeTypeOverrideException() throws Exception {
"[{k, v}]", "[{k, p}]", "buildspec.yml", "5", SourceType.GITHUB_ENTERPRISE.toString(), "https://1.0.0.0.86/my_repo",
EnvironmentType.LINUX_CONTAINER.toString(), "aws/codebuild/openjdk-8", "invalidComputeType", CacheType.NO_CACHE.toString(), "",
LogsConfigStatusType.ENABLED.toString(), "group", "stream", LogsConfigStatusType.ENABLED.toString(), "location",
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString());
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString(), BooleanValue.False.toString());
ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);

Expand All @@ -220,7 +220,7 @@ public void testCacheTypeOverrideException() throws Exception {
"[{k, v}]", "[{k, p}]", "buildspec.yml", "5", SourceType.GITHUB_ENTERPRISE.toString(), "https://1.0.0.0.86/my_repo",
EnvironmentType.LINUX_CONTAINER.toString(), "aws/codebuild/openjdk-8", ComputeType.BUILD_GENERAL1_SMALL.toString(), "invalidCacheType", "",
LogsConfigStatusType.ENABLED.toString(), "group", "stream", LogsConfigStatusType.ENABLED.toString(), "location",
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString());
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString(), BooleanValue.False.toString());
ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);

Expand All @@ -241,7 +241,7 @@ public void testCloudWatchLogsStatusOverrideException() throws Exception {
"[{k, v}]", "[{k, p}]", "buildspec.yml", "5", SourceType.GITHUB_ENTERPRISE.toString(), "https://1.0.0.0.86/my_repo",
EnvironmentType.LINUX_CONTAINER.toString(), "aws/codebuild/openjdk-8", ComputeType.BUILD_GENERAL1_SMALL.toString(), CacheType.NO_CACHE.toString(), "",
"invalidCloudWatchLogsStatus", "group", "stream", LogsConfigStatusType.ENABLED.toString(), "location",
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString());
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString(), BooleanValue.False.toString());
ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);

Expand All @@ -262,7 +262,7 @@ public void testS3LogsStatusOverrideException() throws Exception {
"[{k, v}]", "[{k, p}]", "buildspec.yml", "5", SourceType.GITHUB_ENTERPRISE.toString(), "https://1.0.0.0.86/my_repo",
EnvironmentType.LINUX_CONTAINER.toString(), "aws/codebuild/openjdk-8", ComputeType.BUILD_GENERAL1_SMALL.toString(), CacheType.NO_CACHE.toString(), "",
LogsConfigStatusType.ENABLED.toString(), "group", "stream", "invalidS3LogsStatus", "location",
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString());
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString(), BooleanValue.False.toString());
ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);

Expand All @@ -283,7 +283,7 @@ public void testSourceTypeOverrideException() throws Exception {
"[{k, v}]", "[{k, p}]", "buildspec.yml", "5", "invalidSourceType", "https://1.0.0.0.86/my_repo",
EnvironmentType.LINUX_CONTAINER.toString(), "aws/codebuild/openjdk-8", ComputeType.BUILD_GENERAL1_SMALL.toString(), CacheType.NO_CACHE.toString(), "",
LogsConfigStatusType.ENABLED.toString(), "group", "stream", LogsConfigStatusType.ENABLED.toString(), "location",
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString());
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString(), BooleanValue.False.toString());
ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);

Expand All @@ -304,7 +304,7 @@ public void testEnvironmentTypeOverrideException() throws Exception {
"[{k, v}]", "[{k, p}]", "buildspec.yml", "5", SourceType.GITHUB_ENTERPRISE.toString(), "https://1.0.0.0.86/my_repo",
"invalidEnvironmentType", "aws/codebuild/openjdk-8", ComputeType.BUILD_GENERAL1_SMALL.toString(), CacheType.NO_CACHE.toString(), "",
LogsConfigStatusType.ENABLED.toString(), "group", "stream", LogsConfigStatusType.ENABLED.toString(), "location",
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString());
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString(), BooleanValue.False.toString());
ArgumentCaptor<Result> savedResult = ArgumentCaptor.forClass(Result.class);
test.perform(build, ws, launcher, listener, mockStepContext);

Expand All @@ -329,7 +329,7 @@ public void testBuildParameters() throws Exception {
"[{k, v}]", "", "buildspec.yml", "5", SourceType.GITHUB_ENTERPRISE.toString(), "https://1.0.0.0.86/my_repo",
EnvironmentType.LINUX_CONTAINER.toString(), "aws/codebuild/openjdk-8", ComputeType.BUILD_GENERAL1_SMALL.toString(), CacheType.NO_CACHE.toString(), "",
LogsConfigStatusType.ENABLED.toString(), "group", "stream", LogsConfigStatusType.ENABLED.toString(), "location",
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString());
"arn:aws:s3:::my_bucket/certificate.pem", "my_service_role", BooleanValue.False.toString(), BooleanValue.False.toString(), BooleanValue.False.toString());

cb.perform(build, ws, launcher, listener, mockStepContext);

Expand Down

0 comments on commit dfd9268

Please sign in to comment.