/*
* Copyright 2008-2010 Xebia and the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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.
*/
package fr.xebia.workshop.continuousdelivery;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import javax.annotation.Nonnull;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.xebia.cloud.cloudinit.FreemarkerUtils;
/**
* Creates a job in a Jenkins server for a "Petclinic" project hosted on Github.
*
* Example:
*
* <pre>
* new PetclinicJenkinsJobCreator("http://ec2-46-137-62-232.eu-west-1.compute.amazonaws.com:8080").create(new PetclinicProjectInstance("xebia-guest", "42"))
* .triggerBuild();
* </pre>
*/
public class PetclinicJenkinsJobCreator {
private static final Logger logger = LoggerFactory.getLogger(PetclinicJenkinsJobCreator.class);
private final String jenkinsUrl;
public PetclinicJenkinsJobCreator(@Nonnull String jenkinsUrl) {
this.jenkinsUrl = checkNotNull(jenkinsUrl);
checkArgument(jenkinsUrl.startsWith("http://"), "Invalid URL provided for Jenkins server: " + jenkinsUrl);
}
public PostCreationActions create(@Nonnull PetclinicJobInstance project) {
checkNotNull(project);
HttpPost post = new HttpPost(jenkinsUrl + "/createItem?name=" + project.getProjectName());
Map<String, Object> parameters = newHashMap();
parameters.put("githubAccountName", project.getGithubAccountName());
parameters.put("projectName", project.getProjectName());
parameters.put("groupId", project.getGroupId());
parameters.put("artifactId", project.getArtifactId());
String jobConfig = FreemarkerUtils.generate(parameters, "/fr/xebia/workshop/continuousdelivery/petclinic-jenkins-job-config.xml.ftl");
HttpEntity httpEntity;
try {
httpEntity = new StringEntity(jobConfig, "text/xml", "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Unsupported UTF-8 should never occur", e);
}
post.setEntity(httpEntity);
logger.info("Creating job {}: {}", project.getProjectName(), post.getURI());
new Client().post(post);
return new PostCreationActions(jenkinsUrl, project);
}
public static class JobCreationException extends RuntimeException {
private static final long serialVersionUID = -559471701873832122L;
public JobCreationException(String message) {
super(message);
}
public JobCreationException(String message, Throwable cause) {
super(message, cause);
}
}
private static class Client {
void post(HttpPost post) {
HttpClient client = new DefaultHttpClient();
try {
logger.debug("Executing request {}", post.getRequestLine());
HttpResponse response;
try {
response = client.execute(post);
} catch (Exception e) {
throw new JobCreationException("Could not execute request", e);
}
logger.debug("Response status: {}", response.getStatusLine());
if (!newHashSet(HttpStatus.SC_OK, HttpStatus.SC_MOVED_TEMPORARILY).contains(response.getStatusLine().getStatusCode())) {
try {
logger.warn(EntityUtils.toString(response.getEntity()));
} catch (Exception e) {
logger.warn("Could not print entity");
}
throw new JobCreationException(response.getStatusLine().toString());
}
} finally {
client.getConnectionManager().shutdown();
}
}
}
public static class PostCreationActions {
private final String jenkinsUrl;
private final PetclinicJobInstance project;
public PostCreationActions(String jenkinsUrl, PetclinicJobInstance project) {
this.jenkinsUrl = jenkinsUrl;
this.project = project;
}
/**
* Triggers a build so that dependencies are loaded.
*/
public void triggerBuild() {
logger.info("Trigger build of {}", project.getProjectName());
new Client().post(new HttpPost(String.format("%s/job/%s/build", jenkinsUrl, project.getProjectName())));
}
}
}