Skip to content

Commit

Permalink
JENKINS-28441
Browse files Browse the repository at this point in the history
Refactoring for nested descriptors

JENKINS-28442
Added Code & Configuration / Code / Configuration deployment options
  • Loading branch information
cast committed May 17, 2015
1 parent 7ee796b commit efcd284
Show file tree
Hide file tree
Showing 12 changed files with 418 additions and 133 deletions.
16 changes: 13 additions & 3 deletions pom.xml
Expand Up @@ -30,7 +30,7 @@
<developerConnection>scm:git:https://github.com/jenkinsci/aws-lambda-plugin.git</developerConnection>
<url>https://github.com/jenkinsci/aws-lambda-plugin</url>
<tag>aws-lambda-0.1.7</tag>
</scm>
</scm>

<organization>
<name>XT-i</name>
Expand All @@ -44,16 +44,26 @@
</developer>
</developers>

<properties>
<aws.version>1.9.35</aws.version>
<jsonpath.version>2.0.0</jsonpath.version>
</properties>

<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-core</artifactId>
<version>1.9.22</version>
<version>${aws.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-lambda</artifactId>
<version>1.9.22</version>
<version>${aws.version}</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>${jsonpath.version}</version>
</dependency>
</dependencies>

Expand Down
Expand Up @@ -32,7 +32,10 @@
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.tasks.*;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.util.FormValidation;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
Expand All @@ -47,7 +50,7 @@ public class AWSLambdaPublisher extends Notifier{
List<LambdaVariables> lambdaVariablesList = new ArrayList<LambdaVariables>();

@DataBoundConstructor
public AWSLambdaPublisher(List<LambdaVariables> lambdaVariablesList, boolean PublishUnstable) {
public AWSLambdaPublisher(List<LambdaVariables> lambdaVariablesList) {
this.lambdaVariablesList = lambdaVariablesList;
}

Expand Down Expand Up @@ -85,8 +88,11 @@ public boolean perform(LambdaVariables lambdaVariables,AbstractBuild<?, ?> build
executionVariables.expandVariables(build.getEnvironment(listener));
LambdaUploader lambdaUploader = new LambdaUploader(executionVariables, build, listener);

lambdaUploader.upload();
build.addAction(new LambdaProminentAction(executionVariables.getFunctionName(), lambdaUploader.getLambdaResultConforms()));
Boolean lambdaSuccess = lambdaUploader.upload();
if(!lambdaSuccess){
build.setResult(Result.FAILURE);
}
build.addAction(new LambdaProminentAction(executionVariables.getFunctionName(), lambdaSuccess));
return true;
} catch (Exception exc) {
throw new RuntimeException(exc);
Expand Down
Expand Up @@ -44,9 +44,9 @@ public LambdaProminentAction(String functionName, Boolean conforms) {
bigIconFileName = "/plugin/aws-lambda/images/Lambda_48.png";
displayName = "Uploaded Lambda: " + functionName;
}else {
iconFileName = "/plugin/aws-lambda/images/Lambda_grey_24.png";
bigIconFileName = "/plugin/aws-lambda/images/Lambda_grey_48.png";
displayName = "Uploaded Bad Lambda: " + functionName;
iconFileName = "/plugin/aws-lambda/images/Lambda_24_grey.png";
bigIconFileName = "/plugin/aws-lambda/images/Lambda_48_grey.png";
displayName = "Lambda Failure: " + functionName;
}
}

Expand Down
116 changes: 26 additions & 90 deletions src/main/java/com/xti/jenkins/plugin/awslambda/LambdaUploader.java
Expand Up @@ -26,118 +26,54 @@
* #L%
*/

import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSCredentialsProviderChain;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.internal.StaticCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.AWSLambdaClient;
import com.amazonaws.services.lambda.model.UploadFunctionRequest;
import com.amazonaws.services.lambda.model.UploadFunctionResult;
import com.xti.jenkins.plugin.awslambda.service.JenkinsLogger;
import com.xti.jenkins.plugin.awslambda.service.LambdaClientConfig;
import com.xti.jenkins.plugin.awslambda.service.LambdaService;
import hudson.FilePath;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import org.apache.commons.lang.StringUtils;

import java.io.*;

public class LambdaUploader {
private final PrintStream logger;
private final FilePath artifactLocation;

private JenkinsLogger logger;
private LambdaVariables config;
private AWSLambda lambda;
private File artifact;
private Boolean lambdaResultConforms = false;
private LambdaService lambda;
private FilePath artifactLocation = null;

public LambdaUploader(LambdaVariables config,
AbstractBuild<?, ?> build, BuildListener listener) throws IOException, InterruptedException {
public LambdaUploader(LambdaVariables config, AbstractBuild<?, ?> build, BuildListener listener) throws IOException, InterruptedException {
this.config = config;
this.logger = listener.getLogger();

this.artifactLocation = new FilePath(build.getWorkspace(), config.getArtifactLocation());
logger = new JenkinsLogger(listener.getLogger());
LambdaClientConfig lambdaClientConfig = new LambdaClientConfig(config.getAwsAccessKeyId(), config.getAwsSecretKey(), config.getAwsRegion());
lambda = new LambdaService(lambdaClientConfig.getClient(), logger);
if(StringUtils.isNotEmpty(config.getArtifactLocation())) {
artifactLocation = new FilePath(build.getWorkspace(), config.getArtifactLocation());
}
}

public void upload() throws IOException, InterruptedException {
log("Starting lambda upload procedure");
getArtifactFile(artifactLocation);
setupLambdaClient();
uploadLambdaFunction();
public Boolean upload() throws IOException, InterruptedException {
logger.log("%nStarting lambda upload procedure");
File zipFile = null;
if(artifactLocation != null){
zipFile = getArtifactFile(artifactLocation);
}
return lambda.processLambdaDeployment(config, zipFile, UpdateModeValue.fromString(config.getUpdateMode()));
}

private void getArtifactFile(FilePath artifactLocation) throws IOException, InterruptedException {
private File getArtifactFile(FilePath artifactLocation) throws IOException, InterruptedException {
File resultFile = File.createTempFile("awslambda-", ".zip");

if (!artifactLocation.isDirectory()) {
log("Copying zip file");
logger.log("Copying zip file");
artifactLocation.copyTo(new FileOutputStream(resultFile));
} else {
log("Zipping folder ..., copying zip file");
logger.log("Zipping folder ..., copying zip file");
artifactLocation.zip(new FileOutputStream(resultFile));
}

log("File Name: %s%nAbsolute Path: %s%nFile Size: %d", resultFile.getName(), resultFile.getAbsolutePath(), resultFile.length());
artifact = resultFile;
logger.log("File Name: %s%nAbsolute Path: %s%nFile Size: %d", resultFile.getName(), resultFile.getAbsolutePath(), resultFile.length());
return resultFile;
}

private void setupLambdaClient() {
AWSCredentialsProvider credentials = new AWSCredentialsProviderChain(
new StaticCredentialsProvider(
new BasicAWSCredentials(
config.getAwsAccessKeyId(),
config.getAwsSecretKey())
)
);
Region region = Region.getRegion(Regions.fromName(config.getAwsRegion()));

lambda = new AWSLambdaClient(credentials);
lambda.setRegion(region);
log("Lambda credentials set for region: %s", region);
}

private void uploadLambdaFunction() throws FileNotFoundException {
UploadFunctionRequest uploadRequest = new UploadFunctionRequest()
.withDescription(config.getDescription())
.withFunctionName(config.getFunctionName())
.withHandler(config.getHandler())
.withMemorySize(config.getMemorySize())
.withTimeout(config.getTimeout())
.withMode(config.getMode())
.withRole(config.getRole())
.withRuntime(config.getRuntime())
.withFunctionZip(new FileInputStream(artifact));
log("%nLambda upload request:%n%s%n", uploadRequest.toString());

UploadFunctionResult uploadFunctionResult = lambda.uploadFunction(uploadRequest);
log("Lambda upload response:%n%s%n", uploadFunctionResult.toString());

verifyUploadFunctionResult(uploadRequest, uploadFunctionResult);
}

private void verifyUploadFunctionResult(UploadFunctionRequest request, UploadFunctionResult result) {
if(
result.getFunctionName().equals(request.getFunctionName())
&& result.getHandler().equals(request.getHandler())
&& result.getMemorySize().equals(request.getMemorySize()) || request.getMemorySize() == null
&& result.getTimeout().equals(request.getTimeout()) || request.getTimeout() == null
&& result.getRuntime().equals(request.getRuntime())
&& result.getMode().equals(request.getMode())
&& result.getRole().equals(request.getRole())){
log("Lambda function response conforms with request%n");
lambdaResultConforms = true;
}else {
log("Warning: Lambda function response does not conform with request! " +
"%nCheck AWS console and plugin configuration%n");
lambdaResultConforms = false;
}
}

public Boolean getLambdaResultConforms() {
return lambdaResultConforms;
}

void log(String mask, Object... args) {
logger.println(String.format(mask, args));
}
}
77 changes: 62 additions & 15 deletions src/main/java/com/xti/jenkins/plugin/awslambda/LambdaVariables.java
Expand Up @@ -27,10 +27,15 @@
*/

import hudson.EnvVars;
import hudson.Extension;
import hudson.Util;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.ListBoxModel;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;

public class LambdaVariables {
public class LambdaVariables extends AbstractDescribableImpl<LambdaVariables> {
private String awsAccessKeyId;
private String awsSecretKey;
private String awsRegion;
Expand All @@ -39,14 +44,14 @@ public class LambdaVariables {
private String functionName;
private String handler;
private Integer memorySize;
private String mode;
private String role;
private String runtime;
private Integer timeout;
private boolean successOnly;
private String updateMode;

@DataBoundConstructor
public LambdaVariables(String awsAccessKeyId, String awsSecretKey, String awsRegion, String artifactLocation, String description, String functionName, String handler, Integer memorySize, String mode, String role, String runtime, Integer timeout, boolean successOnly) {
public LambdaVariables(String awsAccessKeyId, String awsSecretKey, String awsRegion, String artifactLocation, String description, String functionName, String handler, Integer memorySize, String role, String runtime, Integer timeout, boolean successOnly, String updateMode) {
this.awsAccessKeyId = awsAccessKeyId;
this.awsSecretKey = awsSecretKey;
this.awsRegion = awsRegion;
Expand All @@ -55,11 +60,11 @@ public LambdaVariables(String awsAccessKeyId, String awsSecretKey, String awsReg
this.functionName = functionName;
this.handler = handler;
this.memorySize = memorySize;
this.mode = mode;
this.role = role;
this.runtime = runtime;
this.timeout = timeout;
this.successOnly = successOnly;
this.updateMode = updateMode;
}

public String getAwsAccessKeyId() {
Expand Down Expand Up @@ -94,10 +99,6 @@ public Integer getMemorySize() {
return memorySize;
}

public String getMode() {
return mode;
}

public String getRole() {
return role;
}
Expand All @@ -110,6 +111,10 @@ public Integer getTimeout() {
return timeout;
}

public String getUpdateMode() {
return updateMode;
}

public boolean getSuccessOnly(){
return successOnly;
}
Expand Down Expand Up @@ -146,10 +151,6 @@ public void setMemorySize(Integer memorySize) {
this.memorySize = memorySize;
}

public void setMode(String mode) {
this.mode = mode;
}

public void setRole(String role) {
this.role = role;
}
Expand All @@ -162,28 +163,74 @@ public void setTimeout(Integer timeout) {
this.timeout = timeout;
}

public void setUpdateMode(String updateMode) {
this.updateMode = updateMode;
}

public void setSuccessOnly(boolean successOnly) {
this.successOnly = successOnly;
}

public void expandVariables(EnvVars env) {
public void expandVariables(EnvVars env) {
awsAccessKeyId = expand(awsAccessKeyId, env);
awsSecretKey = expand(awsSecretKey, env);
awsRegion = expand(awsRegion, env);
artifactLocation = expand(artifactLocation, env);
description = expand(description, env);
functionName = expand(functionName, env);
handler = expand(handler, env);
mode = expand(mode, env);
role = expand(role, env);
runtime = expand(runtime, env);
}

public LambdaVariables getClone(){
return new LambdaVariables(awsAccessKeyId, awsSecretKey, awsRegion, artifactLocation, description, functionName, handler, memorySize, mode, role, runtime, timeout, successOnly);
return new LambdaVariables(awsAccessKeyId, awsSecretKey, awsRegion, artifactLocation, description, functionName, handler, memorySize, role, runtime, timeout, successOnly, updateMode);
}

private String expand(String value, EnvVars env) {
return Util.replaceMacro(value.trim(), env);
}

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

/* TODO: conditionally check based on UpdateMode
public FormValidation doCheckTimeout(@QueryParameter String value) {
try {
Integer.parseInt(value);
return FormValidation.ok();
} catch (NumberFormatException e) {
return FormValidation.error("Not a number");
}
}
*/

/* TODO: conditionally check based on UpdateMode
public FormValidation doCheckMemorySize(@QueryParameter String value) {
try {
Integer.parseInt(value);
return FormValidation.ok();
} catch (NumberFormatException e) {
return FormValidation.error("Not a number");
}
}
*/

public ListBoxModel doFillUpdateModeItems(@QueryParameter String updateMode) {
ListBoxModel items = new ListBoxModel();
for (UpdateModeValue updateModeValue : UpdateModeValue.values()) {
items.add(new ListBoxModel.Option(updateModeValue.getDisplayName(), updateModeValue.getMode(), updateModeValue.getMode().equals(updateMode)));
}
return items;
}

/**
* This human readable name is used in the configuration screen.
*/
public String getDisplayName() {
return "Deploy into Lambda";
}


}
}

0 comments on commit efcd284

Please sign in to comment.