@@ -63,23 +64,31 @@
repo.jenkins-ci.org
- http://repo.jenkins-ci.org/public/
+ https://repo.jenkins-ci.org/public/
+
+
+ central
+ Central Repository
+ https://repo.maven.apache.org/maven2
+ default
+
+ false
+
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.4
@@ -94,6 +103,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 +171,26 @@
1.9
test
-
-
+
+
+
+ org.codehaus.mojo
+ findbugs-maven-plugin
+ 3.0.4
+
+ ${maven.findbugs.failure.strict}
+
+
+
+ org.jenkins-ci.tools
+ maven-hpi-plugin
+
+ true
+
+
+
+
+
diff --git a/release.properties b/release.properties
new file mode 100644
index 0000000..876736c
--- /dev/null
+++ b/release.properties
@@ -0,0 +1,12 @@
+#release configuration
+#Wed Apr 27 20:59:37 IDT 2022
+scm.tagNameFormat=@{project.artifactId}-@{project.version}
+pushChanges=true
+scm.url=scm\:git\:https\://github.com/jenkinsci/cloudshell-sandbox-plugin.git
+preparationGoals=clean install
+remoteTagging=true
+projectVersionPolicyId=default
+scm.commentPrefix=[maven-release-plugin]
+exec.additionalArguments=
+exec.snapshotReleasePluginAllowed=false
+completedPhase=check-poms
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
+