package de.codecentric.jenkins.dashboard;
import hudson.Extension;
import hudson.model.Item;
import hudson.model.Result;
import hudson.model.TopLevelItem;
import hudson.model.ViewGroup;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Cause;
import hudson.model.Descriptor;
import hudson.model.ModifiableItemGroup;
import hudson.model.ParametersAction;
import hudson.model.StringParameterValue;
import hudson.model.View;
import hudson.model.ViewDescriptor;
import hudson.model.queue.QueueTaskFuture;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.bind.JavaScriptMethod;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import de.codecentric.jenkins.dashboard.api.environments.ServerEnvironment;
import de.codecentric.jenkins.dashboard.api.repositories.Artifact;
import de.codecentric.jenkins.dashboard.api.repositories.RepositoryInterface;
import de.codecentric.jenkins.dashboard.impl.environments.ec2.EC2Connector;
import de.codecentric.jenkins.dashboard.impl.repositories.RepositoryTypes;
import de.codecentric.jenkins.dashboard.impl.repositories.artifactory.ArtifactoryConnector;
import de.codecentric.jenkins.dashboard.impl.repositories.nexus.NexusConnector;
/**
* Central class for the dashboard view. When adding a new view to Jenkins page,
* this DashboardView will appear. Each time this view is loaded, this class
* will be called.
*
*/
public class DashboardView extends View {
private final static Logger LOGGER = Logger.getLogger(DashboardView.class.getName());
@Extension
public static final DashboardViewDescriptor DESCRIPTOR = new DashboardViewDescriptor();
public static final String PARAM_VERSION = "VERSION";
public static final String PARAM_ENVIRONMENT = "ENVIRONMENT";
public static final String PARAM_EC2_REGION = "EC2_REGION";
public static final String PARAM_AWS_KEY= "AWS_KEY";
private boolean showDeployField;
private String groupId = "";
private String artefactId = "";
private List<Environment> environments;
public DashboardView(final String name) {
super(name);
}
public DashboardView(final String name, final ViewGroup owner) {
super(name, owner);
}
@DataBoundConstructor
public DashboardView(final String name, final boolean showDeployField, final String groupId, final String artefactId, final List<Environment> environments) {
this(name);
setShowDeployField(showDeployField);
setGroupId(groupId);
setArtefactId(artefactId);
setEnvironments(environments);
}
@Override
public ViewDescriptor getDescriptor() {
return DESCRIPTOR;
}
/**
* Gets all the items in this collection in a read-only view.
*/
@Override
public Collection<TopLevelItem> getItems() {
return new ArrayList<TopLevelItem>();
}
/**
* Checks if the job is in this collection.
*/
@Override
public boolean contains(final TopLevelItem item) {
return false;
}
@JavaScriptMethod
public String deploy(String version, String environment) {
LOGGER.info("Deploy version " + version + " to environment " + environment);
// Get the environment with corresponding build-job
Environment buildEnvironment = null;
for (Environment env : environments) {
if (env.getAwsInstance().equals(environment)) {
buildEnvironment = env;
break;
}
}
final AbstractProject buildJob = Jenkins.getInstance().getItemByFullName(buildEnvironment.getBuildJob(), AbstractProject.class);
LOGGER.info("Executing job: " + buildJob);
if (buildJob == null) {
return String.format(Messages.DashboardView_buildJobNotFound(), buildEnvironment.getName());
}
if ((!buildJob.isBuildable()) || (!buildJob.isParameterized())) {
return Messages.DashboardView_deploymentCannotBeExecuted();
}
final ParametersAction versionParam = new ParametersAction(new StringParameterValue(PARAM_VERSION, version));
final ParametersAction environmentParam = new ParametersAction(new StringParameterValue(PARAM_ENVIRONMENT, environment));
final ParametersAction ec2RegionParam = new ParametersAction(new StringParameterValue(PARAM_EC2_REGION, environment));
final ParametersAction awsKeyParam = new ParametersAction(new StringParameterValue(PARAM_AWS_KEY, environment));
List<ParametersAction> actions = Arrays.asList(versionParam, environmentParam, ec2RegionParam, awsKeyParam);
QueueTaskFuture<AbstractBuild> scheduledBuild = buildJob.scheduleBuild2(2, new Cause.UserIdCause(), actions);
Result result = Result.FAILURE;
try {
AbstractBuild finishedBuild = scheduledBuild.get();
result = finishedBuild.getResult();
LOGGER.info("Build finished with result: " + result + " completed in: " + finishedBuild.getDurationString() + ". ");
} catch (Exception e) {
LOGGER.severe("Error while waiting for build " + scheduledBuild.toString() + ".");
LOGGER.severe(e.getMessage());
LOGGER.severe(ExceptionUtils.getFullStackTrace(e));
return String.format(Messages.DashboardView_buildJobFailed(), buildJob.getName());
}
if (result == Result.SUCCESS) {
return String.format(Messages.DashboardView_buildJobScheduledSuccessfully(), buildJob.getName());
}
return String.format(Messages.DashboardView_buildJobSchedulingFailed(), buildJob.getName());
}
/**
* Handles the configuration submission. Load view-specific properties here.
*/
@Override
protected synchronized void submit(final StaplerRequest req) throws IOException, ServletException, Descriptor.FormException {
LOGGER.info("DashboardView submit configuration");
req.bindJSON(this, req.getSubmittedForm()); // Mapping the JSON directly should work
}
/**
* Creates a new {@link hudson.model.Item} in this collection.
*
* This method should call
* {@link ModifiableItemGroup#doCreateItem(org.kohsuke.stapler.StaplerRequest, org.kohsuke.stapler.StaplerResponse)}
* and then add the newly created item to this view.
*
* @return null if it fails
*/
@Override
public Item doCreateItem(final StaplerRequest req, final StaplerResponse rsp) throws IOException, ServletException {
return Jenkins.getInstance().doCreateItem(req, rsp);
}
public String getDisplayDeployField() {
return showDeployField ? "" : "display:none;";
}
public boolean getShowDeployField() {
return showDeployField;
}
public void setShowDeployField(boolean showDeployField) {
this.showDeployField = showDeployField;
}
public String getArtefactId() {
return artefactId;
}
public void setArtefactId(final String artefactId) {
this.artefactId = artefactId;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public List<Artifact> getArtifacts() {
LOGGER.info("Getting artifacts for " + DESCRIPTOR.getRepositoryType());
// User needs to configure an artifact repository on the global config
// page
if (DESCRIPTOR.getRepositoryType() == null) {
return new ArrayList<Artifact>();
}
RepositoryInterface repository;
try {
repository = createRepository();
} catch (URISyntaxException e) {
e.printStackTrace();
return new ArrayList<Artifact>();
}
return repository.getArtefactList(groupId, artefactId);
}
private RepositoryInterface createRepository() throws URISyntaxException {
URI repositoryURI = new URI(DESCRIPTOR.getRepositoryRestUri());
RepositoryInterface repository;
if (DESCRIPTOR.getRepositoryType().equalsIgnoreCase(RepositoryTypes.ARTIFACTORY.getid())) {
repository = new ArtifactoryConnector(DESCRIPTOR.getUsername(), DESCRIPTOR.getPassword(), repositoryURI);
} else {
repository = new NexusConnector(DESCRIPTOR.getUsername(), DESCRIPTOR.getPassword(), repositoryURI);
}
return repository;
}
public List<ServerEnvironment> getMatchingEC2Environments() {
final List<ServerEnvironment> list = new ArrayList<ServerEnvironment>();
for (Environment env : environments) {
final EC2Connector envConn = EC2Connector.getEC2Connector(env.getCredentials());
if (envConn == null || !envConn.areAwsCredentialsValid()) {
LOGGER.info("Invalid credentials in environment '" + env.getName() + "'");
continue;
}
List<ServerEnvironment> foundEnvironments = envConn.getEnvironmentsByTag(Region.getRegion(Regions.fromName(env.getRegion())), env.getAwsInstance());
updateEnvironmentsWithUrlPrePostFix(foundEnvironments, env);
list.addAll(foundEnvironments);
}
return list;
}
private void updateEnvironmentsWithUrlPrePostFix(List<ServerEnvironment> foundEnvironments, Environment environment) {
for (ServerEnvironment serverEnvironment : foundEnvironments) {
serverEnvironment.setUrlPrefix(environment.getUrlPrefix());
serverEnvironment.setUrlPostfix(environment.getUrlPostfix());
}
}
public List<Environment> getEnvironments() {
return Collections.unmodifiableList(environments);
}
public void setEnvironments(final List<Environment> environmentsList) {
this.environments = environmentsList == null ? new ArrayList<Environment>() : new ArrayList<Environment>(environmentsList);
}
}