Java tutorial
// // Copyright (c) 2013, Skytap, Inc // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // package org.jenkinsci.plugins.skytap; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import hudson.Extension; import hudson.model.AbstractBuild; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.BasicHttpEntity; import org.jenkinsci.plugins.skytap.SkytapBuilder.SkytapAction; import org.jenkinsci.plugins.skytap.SkytapBuilder.SkytapActionDescriptor; import org.kohsuke.stapler.DataBoundConstructor; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.thoughtworks.xstream.annotations.XStreamOmitField; public class CreatePublishURLStep extends SkytapAction { private final String configurationID; private final String configurationFile; private final String urlSaveFilename; private final String permissionOption; private final Boolean hasPassword; private final String urlPassword; // these will be initialized when the step is run @XStreamOmitField private SkytapGlobalVariables globalVars; @XStreamOmitField private String runtimeConfigurationID; @XStreamOmitField private String authCredentials; @DataBoundConstructor public CreatePublishURLStep(String configurationID, String configurationFile, String urlSaveFilename, String permissionOption, RequirePasswordBlock hasPassword) { super("Create Publish URL"); this.configurationFile = configurationFile; this.configurationID = configurationID; this.urlSaveFilename = urlSaveFilename; this.permissionOption = permissionOption; if (hasPassword == null) { this.hasPassword = false; this.urlPassword = null; } else { this.hasPassword = true; this.urlPassword = hasPassword.password; } } public Boolean executeStep(AbstractBuild build, SkytapGlobalVariables globalVars) { JenkinsLogger.defaultLogMessage("----------------------------------------"); JenkinsLogger.defaultLogMessage("Creating Publish URL"); JenkinsLogger.defaultLogMessage("----------------------------------------"); if (preFlightSanityChecks() == false) { return false; } this.globalVars = globalVars; this.authCredentials = SkytapUtils.getAuthCredentials(build); // expand environment variables where it makes sense String expConfigFile = SkytapUtils.expandEnvVars(build, configurationFile); // if user has provided just a filename with no path, default to // place it in their Jenkins workspace if (!expConfigFile.equals("")) { expConfigFile = SkytapUtils.convertFileNameToFullPath(build, expConfigFile); } String expUrlFile = SkytapUtils.expandEnvVars(build, urlSaveFilename); // get runtime config id try { runtimeConfigurationID = SkytapUtils.getRuntimeId(configurationID, expConfigFile); } catch (FileNotFoundException e) { JenkinsLogger.error("Error retrieving configuration id: " + e.getMessage()); return false; } // get all VM ids for config JenkinsLogger.log("Retrieving VM ids for configuration: " + runtimeConfigurationID); List<String> vmList = new ArrayList<String>(); try { vmList = getVMIds(runtimeConfigurationID); } catch (SkytapException e) { JenkinsLogger.error(e.getMessage()); return false; } // create publish set JenkinsLogger.log("Creating publish set ..."); String pubSetUrl = ""; try { pubSetUrl = createPublishSet(runtimeConfigurationID, vmList); } catch (SkytapException e) { JenkinsLogger.error(e.getMessage()); } // get url JenkinsLogger.log("Publish Set URL: " + pubSetUrl); Writer output = null; // if user has provided just a filename with no path, default to // place it in their Jenkins workspace expUrlFile = SkytapUtils.convertFileNameToFullPath(build, expUrlFile); File file = new File(expUrlFile); // write url to file try { output = new BufferedWriter(new FileWriter(file)); output.write(pubSetUrl); output.close(); } catch (IOException e) { JenkinsLogger.error("Skytap Plugin failed to save URL to file: " + expUrlFile); return false; } JenkinsLogger .defaultLogMessage("URL " + pubSetUrl + " successfully created and saved to file: " + expUrlFile); JenkinsLogger.defaultLogMessage("----------------------------------------"); return true; } private String createPublishSet(String confId, List<String> vmList) throws SkytapException { // build request String reqUrl = "https://cloud.skytap.com/configurations/" + confId + "/publish_sets/"; JenkinsLogger.log("Request URL: " + reqUrl); // create request HttpPost hp = SkytapUtils.buildHttpPostRequest(reqUrl, this.authCredentials); // add content to request - vms BasicHttpEntity he = new BasicHttpEntity(); he.setContentEncoding("gzip"); he.setContentType("application/json"); // json string for connected attribute StringBuilder sb = new StringBuilder(""); sb.append("{\"publish_set\":{\"publish_set_type\":\"single_url\","); sb.append("\"vms\":["); // iterate through vm list, adding elements to the array Iterator iter = vmList.iterator(); while (iter.hasNext()) { String vmString = "{\"access\":\"" + this.permissionOption + "\",\"vm_ref\":\"" + iter.next().toString() + "\"}"; if (iter.hasNext()) { vmString += ","; } sb.append(vmString); } // set password if one was provided String passwordString = ""; if (this.hasPassword) { passwordString = "\"" + this.urlPassword + "\""; } else { passwordString = "null"; } sb.append("],\"password\":" + passwordString + ","); sb.append("\"name\":\"Default Publish Set\"}}"); String jsonString = sb.toString(); JenkinsLogger.log("Request Payload: " + jsonString); // {"publish_set":{"publish_set_type":"single_url", // "vms":[{"access":"use","vm_ref":"2128250"}],"password":null,"name":"blah"}} InputStream stream; try { stream = new ByteArrayInputStream(jsonString.getBytes("UTF-8")); Integer len = jsonString.getBytes("UTF-8").length; long llen = len.longValue(); he.setContent(stream); he.setContentLength(llen); } catch (UnsupportedEncodingException e) { JenkinsLogger.error("Error encoding json string for connected attribute: " + e.getMessage()); } hp.setEntity(he); String response = ""; response = SkytapUtils.executeHttpRequest(hp); // check response for errors SkytapUtils.checkResponseForErrors(response); // extract url from response String respUrl = SkytapUtils.getValueFromJsonResponseBody(response, "desktops_url"); return respUrl; } private List<String> getVMIds(String confId) throws SkytapException { List<String> vmList = new ArrayList<String>(); // build request String reqUrl = "https://cloud.skytap.com/configurations/" + confId; HttpGet hg = SkytapUtils.buildHttpGetRequest(reqUrl, this.authCredentials); // extract vm ids String response = SkytapUtils.executeHttpRequest(hg); // check response for errors SkytapUtils.checkResponseForErrors(response); // get id and name of newly created template JsonParser parser = new JsonParser(); JsonElement je = parser.parse(response); JsonArray ja = (JsonArray) je.getAsJsonObject().get("vms"); Iterator iter = ja.iterator(); while (iter.hasNext()) { JsonElement vmElement = (JsonElement) iter.next(); String vmElementId = vmElement.getAsJsonObject().get("id").getAsString(); vmList.add(vmElementId); JenkinsLogger.log("VM ID: " + vmElementId); } return vmList; } // "requirePassword":{"urlPassword":"qsdqweq"} public static class RequirePasswordBlock { private String password; @DataBoundConstructor public RequirePasswordBlock(String urlPassword) { this.password = urlPassword; } } /** * This method is a final check to ensure that user inputs are legitimate. * Any situation where the user has entered both inputs in an either/or scenario * will fail the build. If the user has left both blank where we need one, it will * also fail. * * @return Boolean sanityCheckPassed */ private Boolean preFlightSanityChecks() { // check whether user entered both values for conf id/conf file if (!this.configurationID.equals("") && !this.configurationFile.equals("")) { JenkinsLogger.error( "Values were provided for both configuration ID and file. Please provide just one or the other."); return false; } // check whether we have neither conf id or file if (this.configurationFile.equals("") && this.configurationID.equals("")) { JenkinsLogger.error( "No value was provided for configuration ID or file. Please provide either a valid Skytap configuration ID, or a valid configuration file."); return false; } // check whether no savefile name was provided if (this.urlSaveFilename.equals("")) { JenkinsLogger.error("No value was provided for URL save file. Please provide a valid filename."); return false; } // should there be a password? was one provided? if (this.hasPassword && this.urlPassword.equals("")) { JenkinsLogger.error( "It was indicated the URL should have a password but none was provided. Please provide a password."); return false; } return true; } public String getConfigurationID() { return configurationID; } public String getConfigurationFile() { return configurationFile; } public String getUrlSaveFilename() { return urlSaveFilename; } public String getPermissionOption() { return permissionOption; } public Boolean isHasPassword() { return hasPassword; } public Boolean getHasPassword() { return hasPassword; } public String getUrlPassword() { return urlPassword; } @Extension public static final SkytapActionDescriptor D = new SkytapActionDescriptor(CreatePublishURLStep.class, "Create Publish URL"); }