diff --git a/pom.xml b/pom.xml index 79ddbe1..10f3fea 100644 --- a/pom.xml +++ b/pom.xml @@ -10,12 +10,13 @@ cloudshell-sandbox - 1.6.4-beta + 1.8.3 hpi + 2.9 - 7 + 8 2.2 @@ -63,23 +64,22 @@ repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ + https://repo.jenkins-ci.org/public/ repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ + https://repo.jenkins-ci.org/public/ - com.quali.cloudshell sandbox-api - 1.1.0.14 + 1.3.0.2 @@ -94,6 +94,21 @@ 2.2 + + + com.google.code.gson + gson + 2.8.0 + + + + + org.codehaus.mojo.signature + java18 + 1.0 + signature + + org.jenkins-ci.plugins mailer @@ -147,8 +162,18 @@ 1.9 test - - + + + + org.jenkins-ci.tools + maven-hpi-plugin + + true + + + + + diff --git a/src/main/java/org/jenkinsci/plugins/cloudshell/CloudShellConfig.java b/src/main/java/org/jenkinsci/plugins/cloudshell/CloudShellConfig.java index c63a9ee..3f31f10 100644 --- a/src/main/java/org/jenkinsci/plugins/cloudshell/CloudShellConfig.java +++ b/src/main/java/org/jenkinsci/plugins/cloudshell/CloudShellConfig.java @@ -108,22 +108,31 @@ public FormValidation doTestConnection( return FormValidation.ok("Test completed successfully"); } - public FormValidation doCheckPw(@QueryParameter String value) { - if(value.isEmpty()) + public FormValidation doCheckPw(@QueryParameter String value, @QueryParameter String serverAddress) { + if(serverAddress.isEmpty()) + return FormValidation.ok(); + + if(value.isEmpty()) return FormValidation.errorWithMarkup("Password cannot be empty"); else return FormValidation.ok(); } - public FormValidation doCheckUser(@QueryParameter String value) { + public FormValidation doCheckUser(@QueryParameter String value, @QueryParameter String serverAddress) { + if(serverAddress.isEmpty()) + return FormValidation.ok(); + if(value.isEmpty()) return FormValidation.errorWithMarkup("User cannot be empty"); else return FormValidation.ok(); } - public FormValidation doCheckDomain(@QueryParameter String value) { - if(value.isEmpty()) + public FormValidation doCheckDomain(@QueryParameter String value, @QueryParameter String serverAddress) { + if(serverAddress.isEmpty()) + return FormValidation.ok(); + + if(value.isEmpty()) return FormValidation.errorWithMarkup("Domain cannot be empty"); else return FormValidation.ok(); @@ -131,7 +140,9 @@ public FormValidation doCheckDomain(@QueryParameter String value) { public FormValidation doCheckServerAddress(@QueryParameter String value) { -// String regex = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"; + if(value.isEmpty()) + return FormValidation.ok(); + String regex = "^(https?)://[-a-zA-Z0-9-_.:]*[0-9]"; if(value.matches(regex)) return FormValidation.ok(); @@ -140,6 +151,7 @@ public FormValidation doCheckServerAddress(@QueryParameter String value) { } + @Override public String getDisplayName() { return "CloudShell Build Step"; diff --git a/src/main/java/org/jenkinsci/plugins/cloudshell/builders/StartSandbox.java b/src/main/java/org/jenkinsci/plugins/cloudshell/builders/StartSandbox.java index e0378d4..437e9b9 100644 --- a/src/main/java/org/jenkinsci/plugins/cloudshell/builders/StartSandbox.java +++ b/src/main/java/org/jenkinsci/plugins/cloudshell/builders/StartSandbox.java @@ -15,8 +15,10 @@ package org.jenkinsci.plugins.cloudshell.builders; import com.google.gson.Gson; +import com.quali.cloudshell.Constants; import com.quali.cloudshell.QsServerDetails; import com.quali.cloudshell.SandboxApiGateway; +import com.quali.cloudshell.qsExceptions.ExtendedSandboxApiException; import hudson.Extension; import hudson.Launcher; import hudson.Util; @@ -36,6 +38,7 @@ public class StartSandbox extends CloudShellBuildStep { private final String blueprintName; private final String sandboxDuration; private final int maxWaitForSandboxAvailability; + private int setupTimeout; @CheckForNull private String sandboxDomain; @@ -45,10 +48,11 @@ public class StartSandbox extends CloudShellBuildStep { private String params; @DataBoundConstructor - public StartSandbox(String blueprintName, String sandboxDuration, int maxWaitForSandboxAvailability) { + public StartSandbox(String blueprintName, String sandboxDuration, int maxWaitForSandboxAvailability, int setupTimeout) { this.blueprintName = blueprintName; this.sandboxDuration = sandboxDuration; this.maxWaitForSandboxAvailability = maxWaitForSandboxAvailability; + this.setupTimeout = setupTimeout; } public String getBlueprintName() { @@ -60,6 +64,9 @@ public String getSandboxDuration() { public int getMaxWaitForSandboxAvailability() { return maxWaitForSandboxAvailability; } + public int getSetupTimeout() { + return setupTimeout; + } @CheckForNull public String getParams() { @@ -98,17 +105,30 @@ public boolean perform(final AbstractBuild build, final Launcher launcher, server = new QsServerDetails(server.serverAddress, server.user, server.pw, sandboxDomain, server.ignoreSSL); } - SandboxApiGateway gateway = new SandboxApiGateway(new QsJenkinsTaskLogger(listener), server); - String sandboxId = gateway.TryStartBlueprint(blueprintName, - Integer.parseInt(sandboxDuration), - true, - (sandboxName == null || sandboxName.isEmpty()) ? null : sandboxName, - gateway.TryParseBlueprintParams(params), - maxWaitForSandboxAvailability); - - Gson gson = new Gson(); - String sandboxDetails = gson.toJson(gateway.GetSandboxDetails(sandboxId)); - addSandboxToBuildActions(build, server, sandboxId, sandboxDetails); + int customSetupTimeout =0; + if (setupTimeout == 0) + customSetupTimeout = Constants.CONNECT_TIMEOUT_SECONDS; + else + customSetupTimeout= setupTimeout*60; + + SandboxApiGateway gateway = new SandboxApiGateway(new QsJenkinsTaskLogger(listener), server, customSetupTimeout); + String sandboxId = ""; + try { + sandboxId = gateway.TryStartBlueprint(blueprintName, + Integer.parseInt(sandboxDuration), + true, + (sandboxName == null || sandboxName.isEmpty()) ? null : sandboxName, + gateway.TryParseBlueprintParams(params), + maxWaitForSandboxAvailability); + Gson gson = new Gson(); + String sandboxDetails = gson.toJson(gateway.GetSandboxDetails(sandboxId)); + addSandboxToBuildActions(build, server, sandboxId, sandboxDetails); + } + catch (ExtendedSandboxApiException e) + { + addSandboxToBuildActions(build, server, e.getSandboxId(), ""); + throw e; + } return true; } diff --git a/src/main/java/org/jenkinsci/plugins/cloudshell/publisher/CloudShellPublisherControl.java b/src/main/java/org/jenkinsci/plugins/cloudshell/publisher/CloudShellPublisherControl.java index daeb2eb..7c8c51b 100644 --- a/src/main/java/org/jenkinsci/plugins/cloudshell/publisher/CloudShellPublisherControl.java +++ b/src/main/java/org/jenkinsci/plugins/cloudshell/publisher/CloudShellPublisherControl.java @@ -28,11 +28,6 @@ import java.util.Arrays; import java.util.List; -/** - * Post-build step that allow stop all matched container - * - * @author magnayn - */ public class CloudShellPublisherControl extends Recorder implements Serializable { @DataBoundConstructor diff --git a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep.java b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep.java index 290154e..36735d5 100644 --- a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep.java +++ b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep.java @@ -27,6 +27,8 @@ public class SandboxStartStep extends AbstractStepImpl { @CheckForNull private String params; + private int setupTimeout; + @DataBoundConstructor public SandboxStartStep(@Nonnull String name, int duration, int timeout) { this.name = name; @@ -34,7 +36,6 @@ public SandboxStartStep(@Nonnull String name, int duration, int timeout) { this.timeout = timeout; } - @CheckForNull public String getParams() { return params; @@ -55,6 +56,15 @@ public void setSandboxName(@CheckForNull String sandboxName) { this.sandboxName = Util.fixNull(sandboxName); } + public int getSetupTimeout() { + return setupTimeout; + } + + @DataBoundSetter + public void setSetupTimeout( int setupTimeout) { + this.setupTimeout = setupTimeout; + } + @CheckForNull public String getSandboxDomain() { return sandboxDomain; @@ -91,7 +101,7 @@ public static class SandboxStartStepExecution extends AbstractSynchronousStepExe @Override protected String run() throws Exception { StepsCommon stepsCommon = new StepsCommon(); - return stepsCommon.startSandbox(listener, step.name, step.duration ,step.params, step.sandboxName, step.timeout, step.sandboxDomain); + return stepsCommon.startSandbox(listener, step.name, step.duration ,step.params, step.sandboxName, step.timeout, step.sandboxDomain, step.setupTimeout*60); } private static final long serialVersionUID = 1L; diff --git a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStep.java b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStep.java index 1705ec2..58824b4 100644 --- a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStep.java +++ b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStep.java @@ -25,10 +25,12 @@ package org.jenkinsci.plugins.cloudshell.steps; import com.google.inject.Inject; +import com.quali.cloudshell.Constants; import com.quali.cloudshell.qsExceptions.SandboxApiException; import hudson.EnvVars; import hudson.Extension; import hudson.model.TaskListener; +import jnr.constants.Constant; import net.sf.json.JSONObject; import org.jenkinsci.plugins.workflow.steps.*; import org.kohsuke.stapler.DataBoundConstructor; @@ -53,7 +55,7 @@ public class SandboxStep extends AbstractStepImpl { @Deprecated @DataBoundConstructor - public SandboxStep(@Nonnull String name, int maxDuration, String params, String sandboxName, String sandboxDomain, int timeout) { + public SandboxStep(@Nonnull String name, int maxDuration, String params, String sandboxName, String sandboxDomain, int timeout) { this.name = name; this.maxDuration = maxDuration; this.params = params; @@ -99,7 +101,7 @@ public void stop(@Nonnull Throwable throwable) throws Exception { listener.getLogger().println("Aborting CloudShell Sandbox!"); if (sandboxId != null && !sandboxId.isEmpty()) { - new StepsCommon().stopSandbox(listener, sandboxId, getContext()); + new StepsCommon().stopSandbox(listener, sandboxId, getContext(), Constants.CONNECT_TIMEOUT_SECONDS); } } @@ -110,7 +112,7 @@ private boolean CreateSandbox(StepsCommon stepsCommon) throws KeyManagementException, IOException, InterruptedException { - sandboxId = stepsCommon.startSandbox(listener, step.name, step.maxDuration, step.params, step.sandboxName, step.timeout); + sandboxId = stepsCommon.startSandbox(listener, step.name, step.maxDuration, step.params, step.sandboxName, step.timeout, step.sandboxDomain, Constants.CONNECT_TIMEOUT_SECONDS); return false; } @@ -127,7 +129,7 @@ private static class Callback extends BodyExecutionCallback { private void stopSandbox(StepContext context) { StepsCommon stepsCommon = new StepsCommon(); - stepsCommon.stopSandbox(listener, sandboxId, context); + stepsCommon.stopSandbox(listener, sandboxId, context, Constants.CONNECT_TIMEOUT_SECONDS); } @Override @@ -192,6 +194,5 @@ public Step newInstance(StaplerRequest req, JSONObject formData) throws FormExce String sandboxDomain = formData.getString("sandboxDomain"); return new SandboxStep(name, duration, params, sandboxName, sandboxDomain, timeout); } - } } diff --git a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep.java b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep.java index 1e5d2fa..233b7d8 100644 --- a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep.java +++ b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep.java @@ -8,16 +8,28 @@ import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution; import org.jenkinsci.plugins.workflow.steps.StepContextParameter; import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; import javax.annotation.Nonnull; public class SandboxStopStep extends AbstractStepImpl { - public final String reservationId; + public final String sandboxId; + + private int teardownTimeout; @DataBoundConstructor - public SandboxStopStep(@Nonnull String reservationId) { - this.reservationId = reservationId; + public SandboxStopStep(@Nonnull String sandboxId) { + this.sandboxId = sandboxId; + } + + public int getTeardownTimeout() { + return teardownTimeout; + } + + @DataBoundSetter + public void setTeardownTimeout(int teardownTimeout) { + this.teardownTimeout = teardownTimeout; } @Extension @@ -32,7 +44,7 @@ public DescriptorImpl() { } @Override public String getDisplayName() { - return "stops a cloudshell sandbox"; + return "Stops a CloudShell Sandbox"; } } @@ -49,7 +61,7 @@ public static class SandboxStopStepExecution extends AbstractSynchronousStepExec @Override protected Void run() throws Exception { StepsCommon stepsCommon = new StepsCommon(); - stepsCommon.stopSandbox(listener, step.reservationId, getContext()); + stepsCommon.stopSandbox(listener, step.sandboxId, getContext(), step.teardownTimeout*60); return null; } } diff --git a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/StepsCommon.java b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/StepsCommon.java index 41bb7c7..5b24020 100644 --- a/src/main/java/org/jenkinsci/plugins/cloudshell/steps/StepsCommon.java +++ b/src/main/java/org/jenkinsci/plugins/cloudshell/steps/StepsCommon.java @@ -1,9 +1,9 @@ package org.jenkinsci.plugins.cloudshell.steps; +import com.quali.cloudshell.Constants; import com.quali.cloudshell.QsServerDetails; import com.quali.cloudshell.SandboxApiGateway; import com.quali.cloudshell.qsExceptions.InvalidApiCallException; -import com.quali.cloudshell.qsExceptions.ReserveBluePrintConflictException; import com.quali.cloudshell.qsExceptions.SandboxApiException; import com.quali.cloudshell.qsExceptions.TeardownFailedException; import hudson.model.Result; @@ -18,26 +18,22 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; public class StepsCommon { - String startSandbox(TaskListener listener, String name, int duration, String parameters, String sandboxName, int timeout, String sandboxDomain) + + String startSandbox(TaskListener listener, String name, int duration, String parameters, String sandboxName, int timeout, String sandboxDomain, int sandboxTimeout) throws SandboxApiException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException, InterruptedException { + if (sandboxTimeout == 0) + sandboxTimeout = Constants.CONNECT_TIMEOUT_SECONDS; + if (sandboxDomain == null || sandboxDomain.isEmpty()) { - return InitiateBlueprintStart(name, duration, parameters, sandboxName, timeout, getSandboxApiGateway(listener)); + return InitiateBlueprintStart(name, duration, parameters, sandboxName, timeout, getSandboxApiGateway(listener, sandboxTimeout)); } - return InitiateBlueprintStart(name, duration, parameters, sandboxName, timeout, getSandboxApiGateway(listener, sandboxDomain)); + return InitiateBlueprintStart(name, duration, parameters, sandboxName, timeout, getSandboxApiGateway(listener, sandboxDomain, sandboxTimeout)); } - String startSandbox(TaskListener listener, String name, int duration, String parameters, String sandboxName, int timeout) - throws SandboxApiException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException, InterruptedException { - - return InitiateBlueprintStart(name, duration, parameters, sandboxName, timeout, getSandboxApiGateway(listener)); - } - private String InitiateBlueprintStart(String name, int duration, String parameters, String sandboxName, int timeout, SandboxApiGateway gateway) throws SandboxApiException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException { return gateway.TryStartBlueprint(name, duration, @@ -47,10 +43,12 @@ private String InitiateBlueprintStart(String name, int duration, String paramete timeout); } - void stopSandbox(TaskListener listener, String sandboxId, StepContext context){ + void stopSandbox(TaskListener listener, String sandboxId, StepContext context, int timeout){ + if (timeout == 0) + timeout = Constants.CONNECT_TIMEOUT_SECONDS; listener.getLogger().println("Sandbox plugin: Sandbox Cleanup in progress"); try { - SandboxApiGateway gateway = getSandboxApiGateway(listener); + SandboxApiGateway gateway = getSandboxApiGateway(listener, timeout); gateway.StopSandbox(sandboxId, true); try { gateway.VerifyTeardownSucceeded(sandboxId); @@ -66,12 +64,6 @@ void stopSandbox(TaskListener listener, String sandboxId, StepContext context){ } } - private SandboxApiGateway getSandboxApiGateway(TaskListener listener) throws SandboxApiException { - QsServerDetails server = GetCloudShellServerConfig(); - return new SandboxApiGateway( - new QsJenkinsTaskLogger(listener), - server); - } private QsServerDetails GetCloudShellServerConfig() { CloudShellConfig.DescriptorImpl descriptorImpl = @@ -79,9 +71,16 @@ private QsServerDetails GetCloudShellServerConfig() { return descriptorImpl.getServer(); } - private SandboxApiGateway getSandboxApiGateway(TaskListener listener, String domain) throws SandboxApiException { + private SandboxApiGateway getSandboxApiGateway(TaskListener listener, int sandboxTimeout) throws SandboxApiException { + QsServerDetails server = GetCloudShellServerConfig(); + return new SandboxApiGateway( + new QsJenkinsTaskLogger(listener), + server, sandboxTimeout); + } + + private SandboxApiGateway getSandboxApiGateway(TaskListener listener, String domain, int sandboxTimeout) throws SandboxApiException { QsServerDetails server = GetCloudShellServerConfig(); QsServerDetails tempQsServerDetails = new QsServerDetails(server.serverAddress, server.user, server.pw, domain, server.ignoreSSL); - return new SandboxApiGateway(new QsJenkinsTaskLogger(listener), tempQsServerDetails); + return new SandboxApiGateway(new QsJenkinsTaskLogger(listener), tempQsServerDetails, sandboxTimeout); } } diff --git a/src/main/resources/META-INF/hudson.remoting.ClassFilter b/src/main/resources/META-INF/hudson.remoting.ClassFilter new file mode 100644 index 0000000..2d32325 --- /dev/null +++ b/src/main/resources/META-INF/hudson.remoting.ClassFilter @@ -0,0 +1 @@ +com.quali.cloudshell.QsServerDetails \ No newline at end of file diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/builders/StartSandbox/config.jelly b/src/main/resources/org/jenkinsci/plugins/cloudshell/builders/StartSandbox/config.jelly index 74a5bf3..50edb4b 100644 --- a/src/main/resources/org/jenkinsci/plugins/cloudshell/builders/StartSandbox/config.jelly +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/builders/StartSandbox/config.jelly @@ -12,6 +12,9 @@ + + + diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/builders/StartSandbox/help-setupTimeout.html b/src/main/resources/org/jenkinsci/plugins/cloudshell/builders/StartSandbox/help-setupTimeout.html new file mode 100644 index 0000000..fa8af55 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/builders/StartSandbox/help-setupTimeout.html @@ -0,0 +1,3 @@ +
+ Enter the number of minutes to wait for the sandbox setup to complete +
diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep/config.jelly b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep/config.jelly index 31d931a..4179944 100644 --- a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep/config.jelly +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep/config.jelly @@ -15,6 +15,9 @@ + + + diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep/help-setupTimeout.html b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep/help-setupTimeout.html new file mode 100644 index 0000000..fa8af55 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStartStep/help-setupTimeout.html @@ -0,0 +1,3 @@ +
+ Enter the number of minutes to wait for the sandbox setup to complete +
diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStep/config.jelly b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStep/config.jelly index 121d72f..f8c8656 100644 --- a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStep/config.jelly +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStep/config.jelly @@ -26,5 +26,9 @@ + + + + diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStep/help-sandboxDomain.html b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStep/help-sandboxDomain.html new file mode 100644 index 0000000..e8e8aac --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStep/help-sandboxDomain.html @@ -0,0 +1,3 @@ +
+ Sandbox will be created in the following domain. +
diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep/config.jelly b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep/config.jelly index afc2c41..f1334ea 100644 --- a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep/config.jelly +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep/config.jelly @@ -1,8 +1,11 @@ - - - + - + + + + + + \ No newline at end of file diff --git a/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep/help-teardownTimeout.html b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep/help-teardownTimeout.html new file mode 100644 index 0000000..8387ab1 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/cloudshell/steps/SandboxStopStep/help-teardownTimeout.html @@ -0,0 +1,3 @@ +
+ Enter the number of minutes to wait for the sandbox teardown to complete +