Skip to content

Commit

Permalink
JENKINS-28443
Browse files Browse the repository at this point in the history
Added failure handling for Handled and Unhandled errors
  • Loading branch information
cast committed May 25, 2015
1 parent 804cea1 commit 76072b6
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 9 deletions.
@@ -0,0 +1,46 @@
package com.xti.jenkins.plugin.awslambda;

import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.util.FormValidation;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.QueryParameter;

public abstract class AWSLambdaDescriptor<T extends Describable<T>> extends Descriptor<T> {

//awsAccessKeyId field
public FormValidation doCheckAwsAccessKeyId(@QueryParameter String value) {
if(StringUtils.isEmpty(value)){
return FormValidation.error("Please fill in AWS Access Key Id.");
} else {
return FormValidation.ok();
}
}

//awsSecretKey field
public FormValidation doCheckAwsSecretKey(@QueryParameter String value) {
if(StringUtils.isEmpty(value)){
return FormValidation.error("Please fill in AWS Secret Id.");
} else {
return FormValidation.ok();
}
}

//awsRegion field
public FormValidation doCheckAwsRegion(@QueryParameter String value) {
if(StringUtils.isEmpty(value)){
return FormValidation.error("Please fill in AWS Region.");
} else {
return FormValidation.ok();
}
}

//functionName field
public FormValidation doCheckFunctionName(@QueryParameter String value) {
if(StringUtils.isEmpty(value)){
return FormValidation.error("Please fill in AWS Lambda function name.");
} else {
return FormValidation.ok();
}
}
}
Expand Up @@ -33,7 +33,6 @@
import hudson.Extension;
import hudson.Util;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.ListBoxModel;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;
Expand Down Expand Up @@ -207,7 +206,7 @@ private String expand(String value, EnvVars env) {
}

@Extension // This indicates to Jenkins that this is an implementation of an extension point.
public static class DescriptorImpl extends Descriptor<LambdaVariables> {
public static class DescriptorImpl extends AWSLambdaDescriptor<LambdaVariables> {

/* TODO: conditionally check based on UpdateMode
public FormValidation doCheckTimeout(@QueryParameter String value) {
Expand Down
@@ -0,0 +1,7 @@
package com.xti.jenkins.plugin.awslambda.exception;

public class LambdaInvokeException extends RuntimeException {
public LambdaInvokeException(String message) {
super(message);
}
}
@@ -0,0 +1,8 @@
package com.xti.jenkins.plugin.awslambda.invoke;

import com.xti.jenkins.plugin.awslambda.AWSLambdaDescriptor;
import hudson.model.Describable;

public abstract class AWSInvokeDescriptor<T extends Describable<T>> extends AWSLambdaDescriptor<T> {

}
Expand Up @@ -29,7 +29,10 @@
import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.FormValidation;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;

public class JsonParameterVariables extends AbstractDescribableImpl<JsonParameterVariables> {
private String envVarName;
Expand Down Expand Up @@ -71,6 +74,15 @@ public String getDisplayName() {
return "Environment Variable";
}

//envVarName field
public FormValidation doCheckEnvVarName(@QueryParameter String value) {
if(StringUtils.isEmpty(value)){
return FormValidation.error("Please fill in name of environment variable.");
} else {
return FormValidation.ok();
}
}

}

@Override
Expand Down
Expand Up @@ -26,12 +26,12 @@
* #L%
*/

import com.xti.jenkins.plugin.awslambda.AWSLambdaDescriptor;
import com.xti.jenkins.plugin.awslambda.util.LambdaClientConfig;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Util;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;

Expand Down Expand Up @@ -146,7 +146,7 @@ public LambdaClientConfig getLambdaClientConfig(){
}

@Extension // This indicates to Jenkins that this is an implementation of an extension point.
public static class DescriptorImpl extends Descriptor<LambdaInvokeBuildStepVariables> {
public static class DescriptorImpl extends AWSLambdaDescriptor<LambdaInvokeBuildStepVariables> {

/**
* This human readable name is used in the configuration screen.
Expand Down
Expand Up @@ -26,12 +26,12 @@
* #L%
*/

import com.xti.jenkins.plugin.awslambda.AWSLambdaDescriptor;
import com.xti.jenkins.plugin.awslambda.util.LambdaClientConfig;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Util;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;

Expand Down Expand Up @@ -156,7 +156,7 @@ public LambdaClientConfig getLambdaClientConfig(){
}

@Extension // This indicates to Jenkins that this is an implementation of an extension point.
public static class DescriptorImpl extends Descriptor<LambdaInvokeVariables> {
public static class DescriptorImpl extends AWSLambdaDescriptor<LambdaInvokeVariables> {

/**
* This human readable name is used in the configuration screen.
Expand Down
Expand Up @@ -6,7 +6,9 @@
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.services.lambda.model.LogType;
import com.amazonaws.util.Base64;
import com.xti.jenkins.plugin.awslambda.exception.LambdaInvokeException;
import com.xti.jenkins.plugin.awslambda.invoke.InvokeConfig;
import org.apache.commons.lang.StringUtils;

import java.nio.charset.Charset;

Expand Down Expand Up @@ -51,6 +53,10 @@ public String invokeLambdaFunction(InvokeConfig invokeConfig){
logger.log("Log:%n%s%n", new String(Base64.decode(invokeResult.getLogResult()), Charset.forName("UTF-8")));
}

if(StringUtils.isNotEmpty(invokeResult.getFunctionError())){
throw new LambdaInvokeException("Function returned error of type: " + invokeResult.getFunctionError());
}

return payload;
}
}
Expand Up @@ -26,12 +26,12 @@
* #L%
*/

import com.xti.jenkins.plugin.awslambda.AWSLambdaDescriptor;
import com.xti.jenkins.plugin.awslambda.util.LambdaClientConfig;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Util;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.ListBoxModel;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;
Expand Down Expand Up @@ -195,7 +195,7 @@ private String expand(String value, EnvVars env) {
}

@Extension // This indicates to Jenkins that this is an implementation of an extension point.
public static class DescriptorImpl extends Descriptor<LambdaUploadBuildStepVariables> {
public static class DescriptorImpl extends AWSLambdaDescriptor<LambdaUploadBuildStepVariables> {

/* TODO: conditionally check based on UpdateMode
public FormValidation doCheckTimeout(@QueryParameter String value) {
Expand Down
3 changes: 2 additions & 1 deletion src/main/webapp/help-awsRegion.html
Expand Up @@ -24,5 +24,6 @@
#L%
-->
<div>
AWS Region (eu-west-1, us-east-1, ...)
<p>AWS Region (eu-west-1, us-east-1, ...)</p>
<p><a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html" target="_blank">http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html</a></p>
</div>
Expand Up @@ -5,6 +5,7 @@
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.services.lambda.model.LogType;
import com.xti.jenkins.plugin.awslambda.exception.LambdaInvokeException;
import com.xti.jenkins.plugin.awslambda.invoke.InvokeConfig;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -20,6 +21,7 @@
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

Expand Down Expand Up @@ -66,6 +68,29 @@ public void testInvokeLambdaFunctionAsynchronous() throws Exception {
assertEquals("", result);
}

@Test
public void testInvokeLambdaFunctionAsynchronousError() throws Exception {
InvokeConfig invokeConfig = new InvokeConfig("function", "{\"key1\": \"value1\"}", false, null);

when(awsLambdaClient.invoke(any(InvokeRequest.class)))
.thenReturn(new InvokeResult().withFunctionError("Handled"));

try {
lambdaInvokeService.invokeLambdaFunction(invokeConfig);
fail("Should fail with LambdaInvokeException");
} catch (LambdaInvokeException lie){
assertEquals("Function returned error of type: Handled", lie.getMessage());
}

verify(awsLambdaClient, times(1)).invoke(invokeRequestArg.capture());
InvokeRequest invokeRequest = invokeRequestArg.getValue();
assertEquals("function", invokeRequest.getFunctionName());
assertEquals("{\"key1\": \"value1\"}", new String(invokeRequest.getPayload().array(), Charset.forName("UTF-8")));
assertEquals(InvocationType.Event.toString(), invokeRequest.getInvocationType());
verify(jenkinsLogger).log(eq("Lambda invoke request:%n%s%nPayload:%n%s%n"), anyVararg());
verify(jenkinsLogger).log(eq("Lambda invoke response:%n%s%nPayload:%n%s%n"), anyVararg());
}

@Test
public void testInvokeLambdaFunctionSynchronous() throws Exception {
final String logBase64 = "bGFtYmRh";
Expand Down Expand Up @@ -105,4 +130,48 @@ public void testInvokeLambdaFunctionSynchronous() throws Exception {

assertEquals(responsePayload, result);
}

@Test
public void testInvokeLambdaFunctionSynchronousError() throws Exception {
final String logBase64 = "bGFtYmRh";
final String log = "lambda";
final String requestPayload = "{\"key1\": \"value1\"}";
final String responsePayload = "{\"errorMessage\":\"event_fail\"}";

InvokeConfig invokeConfig = new InvokeConfig("function", requestPayload, true, null);

InvokeResult invokeResult = new InvokeResult()
.withLogResult(logBase64)
.withPayload(ByteBuffer.wrap(responsePayload.getBytes()))
.withFunctionError("Unhandled");

when(awsLambdaClient.invoke(any(InvokeRequest.class)))
.thenReturn(invokeResult);

try {
lambdaInvokeService.invokeLambdaFunction(invokeConfig);
fail("Should fail with LambdaInvokeException");
} catch (LambdaInvokeException lie){
assertEquals("Function returned error of type: Unhandled", lie.getMessage());
}

verify(awsLambdaClient, times(1)).invoke(invokeRequestArg.capture());
InvokeRequest invokeRequest = invokeRequestArg.getValue();
assertEquals("function", invokeRequest.getFunctionName());
assertEquals(LogType.Tail.toString(), invokeRequest.getLogType());
assertEquals(requestPayload, new String(invokeRequest.getPayload().array(), Charset.forName("UTF-8")));
assertEquals(InvocationType.RequestResponse.toString(), invokeRequest.getInvocationType());

ArgumentCaptor<String> stringArgs = ArgumentCaptor.forClass(String.class);
verify(jenkinsLogger).log(eq("Lambda invoke request:%n%s%nPayload:%n%s%n"), stringArgs.capture());
List<String> stringArgValues = stringArgs.getAllValues();
assertEquals(Arrays.asList(invokeRequest.toString(), requestPayload), stringArgValues);

verify(jenkinsLogger).log(eq("Log:%n%s%n"), eq(log));

stringArgs = ArgumentCaptor.forClass(String.class);
verify(jenkinsLogger).log(eq("Lambda invoke response:%n%s%nPayload:%n%s%n"), stringArgs.capture());
stringArgValues = stringArgs.getAllValues();
assertEquals(Arrays.asList(invokeResult.toString(), responsePayload), stringArgValues);
}
}

0 comments on commit 76072b6

Please sign in to comment.