/* * Copyright 2013 Qubell, Inc. * * 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 com.qubell.jenkinsci.plugins.qubell.builders; import com.qubell.jenkinsci.plugins.qubell.JsonParser; import com.qubell.services.Instance; import com.qubell.services.InstanceStatusCode; import hudson.Extension; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.Result; import hudson.util.FormValidation; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import javax.servlet.ServletException; import java.io.IOException; import java.io.PrintStream; import java.util.Map; /** * Represents a build step, which is waiting for the result of previously started asynchronous job * * @author Alex Krupnov */ public class ResultWaitBuilder extends QubellBuilder { private final String jobId; private String jobIdResolved; @DataBoundConstructor public ResultWaitBuilder(String jobId, String timeout, String failureReaction) { super(timeout, InstanceStatusCode.RUNNING, null, failureReaction); this.jobId = jobId; } /** * Performs a build with following steps * <ol> * <li>Picks information about previously started job</li> * <li>Waits for expected instance status</li> * </ol> * If any of steps above failed, fails the job, marks build unstable or ignores the result * * @param build current build * @param launcher build launcher * @param listener build listener * @return true of builder finished successfully, otherwise false */ @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { resolveParameterPlaceholders(build, listener); PrintStream buildLog = listener.getLogger(); Map<String, Object> jobInfo; try { jobInfo = JsonParser.parseMap(build.getWorkspace().child(jobIdResolved).readToString()); } catch (IOException e) { logMessage(buildLog, "Unable to read job file %s", e.getMessage()); build.setResult(Result.FAILURE); return false; } outputFilePath = jobInfo.get(ASYNC_OUTPUT_PATH_KEY).toString(); expectedStatus = InstanceStatusCode.valueOf(jobInfo.get(ASYNC_EXPECTED_STATUS_KEY).toString()); //After variables are recovered and set, they need to be filtered against placeholders resolveParameterPlaceholders(build, listener); Instance instance = new Instance(jobInfo.get(ASYNC_INSTANCE_ID_KEY).toString()); logMessage(buildLog, "Retrieved async job settings, instance id %s, expected status %s, output path %s", instance.getId(), expectedStatus, outputFilePath); return waitForExpectedStatus(build, buildLog, instance); } @Override protected void resolveParameterPlaceholders(AbstractBuild build, BuildListener listener) throws IOException, InterruptedException { super.resolveParameterPlaceholders(build, listener); this.jobIdResolved = resolveVariableMacros(build, listener, this.jobId); } /** * Job id to wait for * * @return id of the job */ public String getJobId() { return jobId; } /** * Descriptor for {@link ResultWaitBuilder}. Used as a singleton. * The class is marked as public so that it can be accessed from views. * See <tt>src/main/resources/com/qubell/jenkinsci/plugins/qubell/builders/RunCommandBuilder/*.jelly</tt> * for the actual HTML fragment for the configuration screen. */ @Extension // This indicates to Jenkins that this is an implementation of an extension point. public static final class ResultWaitDescriptor extends BaseDescriptor { /** * Performs on-the-fly validation of the form field command name * * @param value This parameter receives the value that the user has typed. * @return Indicates the outcome of the validation. This is sent to the browser. */ public FormValidation doCheckJobId(@QueryParameter String value) throws IOException, ServletException { if (value.length() == 0) return FormValidation.error("Please set a job id"); return FormValidation.ok(); } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Qubell: Wait for job completion"; } } }