From 4837a1e662950bd4e0e1f1566d456d4b6f78dc49 Mon Sep 17 00:00:00 2001 From: Marat Mavlyutov Date: Wed, 19 Nov 2014 16:51:18 +0300 Subject: [PATCH] reformat code, spaces instead of tabs --- .../jenkins/plugins/jclouds/PluginImpl.java | 34 +- .../jclouds/blobstore/BlobStoreEntry.java | 62 +- .../jclouds/blobstore/BlobStoreProfile.java | 181 ++- .../jclouds/blobstore/BlobStorePublisher.java | 466 +++--- .../jclouds/compute/ComputeLogger.java | 44 +- .../jclouds/compute/InstancesToRun.java | 110 +- .../jclouds/compute/JCloudsBuildWrapper.java | 208 +-- .../jclouds/compute/JCloudsCleanupThread.java | 74 +- .../plugins/jclouds/compute/JCloudsCloud.java | 797 +++++----- .../jclouds/compute/JCloudsComputer.java | 82 +- .../jclouds/compute/JCloudsLauncher.java | 355 +++-- .../jclouds/compute/JCloudsOneOffSlave.java | 88 +- .../compute/JCloudsRetentionStrategy.java | 106 +- .../plugins/jclouds/compute/JCloudsSlave.java | 341 +++-- .../jclouds/compute/JCloudsSlaveTemplate.java | 1294 ++++++++--------- .../jclouds/compute/internal/NodePlan.java | 68 +- ...nPlannedInstancesAndDestroyAllOnError.java | 96 +- .../internal/RetrySupplierOnException.java | 58 +- .../jclouds/compute/internal/RunningNode.java | 46 +- .../compute/internal/TerminateNodes.java | 98 +- .../compute/internal/package-info.java | 4 +- .../jclouds/internal/BuildListenerLogger.java | 86 +- ...BlobStoreProfileInsideJenkinsLiveTest.java | 66 +- .../blobstore/BlobStoreProfileLiveTest.java | 66 +- .../blobstore/BlobStoreTestFixture.java | 138 +- .../jclouds/compute/ComputeTestFixture.java | 138 +- .../JCloudsCloudInsideJenkinsLiveTest.java | 58 +- .../jclouds/compute/JCloudsCloudLiveTest.java | 58 +- .../jclouds/compute/JCloudsCloudTest.java | 68 +- .../compute/JCloudsSlaveTemplateTest.java | 30 +- .../compute/internal/TerminateNodesTest.java | 122 +- 31 files changed, 2709 insertions(+), 2733 deletions(-) diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/PluginImpl.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/PluginImpl.java index c5d9b362..27c3a915 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/PluginImpl.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/PluginImpl.java @@ -12,24 +12,24 @@ @Extension public class PluginImpl extends Plugin implements Describable { - @Override - public void start() throws Exception { - load(); - } + @Override + public void start() throws Exception { + load(); + } - public Descriptor getDescriptor() { - return (DescriptorImpl) Hudson.getInstance().getDescriptorOrDie(getClass()); - } + public Descriptor getDescriptor() { + return (DescriptorImpl) Hudson.getInstance().getDescriptorOrDie(getClass()); + } - public static PluginImpl get() { - return Hudson.getInstance().getPlugin(PluginImpl.class); - } + public static PluginImpl get() { + return Hudson.getInstance().getPlugin(PluginImpl.class); + } - @Extension - public static final class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return "JClouds PluginImpl"; - } - } + @Extension + public static final class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "JClouds PluginImpl"; + } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreEntry.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreEntry.java index f2a2aee5..ec1fdb0f 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreEntry.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreEntry.java @@ -8,40 +8,40 @@ /** * A simple "bean" for blobstore entries. - * + * * @author Vijay Kiran */ public final class BlobStoreEntry extends AbstractDescribableImpl { - /** - * The container where the file is saved. See http://www.jclouds.org/documentation/userguide/blobstore-guide#container - */ - public String container; - /** - * The sub path under the container where the file is saved. - */ - public String path; - /** - * The source file relative to the workspace directory, which needs to be uploaded to the container. - */ - public String sourceFile; - /** - * Whether or not the sourceFile's path relative to the workspace should be preserved upon upload to the Blobstore. - */ - public boolean keepHierarchy; + /** + * The container where the file is saved. See http://www.jclouds.org/documentation/userguide/blobstore-guide#container + */ + public String container; + /** + * The sub path under the container where the file is saved. + */ + public String path; + /** + * The source file relative to the workspace directory, which needs to be uploaded to the container. + */ + public String sourceFile; + /** + * Whether or not the sourceFile's path relative to the workspace should be preserved upon upload to the Blobstore. + */ + public boolean keepHierarchy; - @DataBoundConstructor - public BlobStoreEntry(String container, String path, String sourceFile, boolean keepHierarchy) { - this.container = container; - this.path = path; - this.sourceFile = sourceFile; - this.keepHierarchy = keepHierarchy; - } + @DataBoundConstructor + public BlobStoreEntry(String container, String path, String sourceFile, boolean keepHierarchy) { + this.container = container; + this.path = path; + this.sourceFile = sourceFile; + this.keepHierarchy = keepHierarchy; + } - @Extension - public static class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return ""; - } - } + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return ""; + } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfile.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfile.java index 68602db5..90bf687f 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfile.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfile.java @@ -17,112 +17,107 @@ /** * Model class for Blobstore profile. User can configure multiple profiles to upload artifacts to different providers. - * + * * @author Vijay Kiran */ public class BlobStoreProfile { - private static final Logger LOGGER = Logger.getLogger(BlobStoreProfile.class.getName()); + private static final Logger LOGGER = Logger.getLogger(BlobStoreProfile.class.getName()); - private String profileName; - private String providerName; - private String identity; - private String credential; + private String profileName; + private String providerName; + private String identity; + private String credential; - @DataBoundConstructor - public BlobStoreProfile(final String profileName, final String providerName, final String identity, final String credential) { - this.profileName = profileName; - this.providerName = providerName; - this.identity = identity; - this.credential = credential; - } + @DataBoundConstructor + public BlobStoreProfile(final String profileName, final String providerName, final String identity, final String credential) { + this.profileName = profileName; + this.providerName = providerName; + this.identity = identity; + this.credential = credential; + } - /** - * Configured profile. - * - * @return - name of the profile. - */ - public String getProfileName() { - return profileName; - } + /** + * Configured profile. + * + * @return - name of the profile. + */ + public String getProfileName() { + return profileName; + } - /** - * Provider Name as per the JClouds Blobstore supported providers. - * - * @return - providerName String - */ - public String getProviderName() { - return providerName; - } + /** + * Provider Name as per the JClouds Blobstore supported providers. + * + * @return - providerName String + */ + public String getProviderName() { + return providerName; + } - /** - * Cloud provider identity. - * - * @return - */ - public String getIdentity() { - return identity; - } + /** + * Cloud provider identity. + * + * @return + */ + public String getIdentity() { + return identity; + } - /** - * Cloud provider credential. - * - * @return - */ - public String getCredential() { - return credential; - } + /** + * Cloud provider credential. + * + * @return + */ + public String getCredential() { + return credential; + } - static final Iterable MODULES = ImmutableSet. of(new EnterpriseConfigurationModule()); + static final Iterable MODULES = ImmutableSet.of(new EnterpriseConfigurationModule()); - static BlobStoreContext ctx(String providerName, String identity, String credential, Properties overrides) { - return ContextBuilder.newBuilder(providerName).credentials(identity, credential).overrides(overrides).modules(MODULES) - .buildView(BlobStoreContext.class); - } + static BlobStoreContext ctx(String providerName, String identity, String credential, Properties overrides) { + return ContextBuilder.newBuilder(providerName).credentials(identity, credential).overrides(overrides).modules(MODULES) + .buildView(BlobStoreContext.class); + } - /** - * Upload the specified file from the - * - * @param filePath - * to container - * - * @param container - * - The container where the file needs to be uploaded. - * @param path - * - The path in container where the file needs to be uploaded. - * @param filePath - * - the {@link FilePath} of the file which needs to be uploaded. - * @throws IOException - * @throws InterruptedException - */ - public void upload(String container, String path, FilePath filePath) throws IOException, InterruptedException { - if (filePath.isDirectory()) { - throw new IOException(filePath + " is a directory"); - } - // correct the classloader so that extensions can be found - Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); - // TODO: endpoint - final BlobStoreContext context = ctx(this.providerName, this.identity, this.credential, new Properties()); - try { - final BlobStore blobStore = context.getBlobStore(); - if (!blobStore.containerExists(container)) { - blobStore.createContainerInLocation(null, container); - } - if (!path.equals("") && !blobStore.directoryExists(container, path)) { - blobStore.createDirectory(container, path); - } - String destPath; - if (path.equals("")) { - destPath = filePath.getName(); - } else { - destPath = path + "/" + filePath.getName(); - } - LOGGER.info("Publishing now to container: " + container + " path: " + destPath); + /** + * Upload the specified file from the + * + * @param filePath to container + * @param container - The container where the file needs to be uploaded. + * @param path - The path in container where the file needs to be uploaded. + * @param filePath - the {@link FilePath} of the file which needs to be uploaded. + * @throws IOException + * @throws InterruptedException + */ + public void upload(String container, String path, FilePath filePath) throws IOException, InterruptedException { + if (filePath.isDirectory()) { + throw new IOException(filePath + " is a directory"); + } + // correct the classloader so that extensions can be found + Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); + // TODO: endpoint + final BlobStoreContext context = ctx(this.providerName, this.identity, this.credential, new Properties()); + try { + final BlobStore blobStore = context.getBlobStore(); + if (!blobStore.containerExists(container)) { + blobStore.createContainerInLocation(null, container); + } + if (!path.equals("") && !blobStore.directoryExists(container, path)) { + blobStore.createDirectory(container, path); + } + String destPath; + if (path.equals("")) { + destPath = filePath.getName(); + } else { + destPath = path + "/" + filePath.getName(); + } + LOGGER.info("Publishing now to container: " + container + " path: " + destPath); Blob blob = context.getBlobStore().blobBuilder(destPath).payload(filePath.read()).build(); context.getBlobStore().putBlob(container, blob); - LOGGER.info("Published " + destPath + " to container " + container + " with profile " + this.profileName); - } finally { - context.close(); - } - } + LOGGER.info("Published " + destPath + " to container " + container + " with profile " + this.profileName); + } finally { + context.close(); + } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStorePublisher.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStorePublisher.java index 7c92061e..c7d98f37 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStorePublisher.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/blobstore/BlobStorePublisher.java @@ -33,243 +33,239 @@ /** * Publishes artifacts to Blobstore configured using JClouds - * + * * @author Vijay Kiran */ public class BlobStorePublisher extends Recorder implements Describable { - private static final Logger LOGGER = Logger.getLogger(BlobStorePublisher.class.getName()); - - private String profileName; - @Extension - public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); - private final List entries; - - /** - * Create a new Blobstore publisher for the cofigured profile identified by profileName - * - * @param profileName - * - the name of the configured profile name - */ - @DataBoundConstructor - public BlobStorePublisher(String profileName, List entries) { - super(); - if (profileName == null) { - // defaults to the first one - BlobStoreProfile[] sites = DESCRIPTOR.getProfiles(); - if (sites.length > 0) - profileName = sites[0].getProfileName(); - } - this.entries = entries; - this.profileName = profileName; - } - - /** - * Get list of entries to be uploaded. - * - * @return - */ - public List getEntries() { - return entries; - } - - /** - * @return - current profile for a profileName or returns the first one if the profileName isn't configured - */ - public BlobStoreProfile getProfile() { - BlobStoreProfile[] profiles = DESCRIPTOR.getProfiles(); - - if (profileName == null && profiles.length > 0) - // default - return profiles[0]; - - for (BlobStoreProfile profile : profiles) { - if (profile.getProfileName().equals(profileName)) - return profile; - } - return null; - } - - public String getName() { - return this.profileName; - } - - public void setName(String profileName) { - this.profileName = profileName; - } - - protected void log(final PrintStream logger, final String message) { - logger.println(StringUtils.defaultString(getDescriptor().getDisplayName()) + " " + message); - } - - /** - * Perform the build step of uploading the configured file entries to the blobstore. - *

- *

    - *
  • If the build result is failure, will not do anything except logging the stuff.
  • - *
  • If the blobstore profile isn't configured, or the uploading failed, the build is set to be unstable.
  • - *
  • If the upload is succesful, the build is set to be stable.
  • - *
- * - * @param build - * - reference to curerent build. - * @param launcher - * - {@link Launcher} - * @param listener - * - {@link BuildListener} - * @return Always returns to indicate that build can continue, so we won't block other steps. - * @throws InterruptedException - * @throws IOException - */ - @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - - if (build.getResult() == Result.FAILURE) { - // build failed. don't post - LOGGER.info("Build failed, not publishing any files to blobstore"); - return true; - } - BlobStoreProfile blobStoreProfile = getProfile(); - if (blobStoreProfile == null) { - log(listener.getLogger(), "No JClouds Blob Store blobStoreProfile is configured."); - build.setResult(Result.UNSTABLE); - return true; - } - log(listener.getLogger(), "Using JClouds blobStoreProfile: " + blobStoreProfile.getProfileName()); - try { - Map envVars = build.getEnvironment(listener); - - for (BlobStoreEntry blobStoreEntry : entries) { - String expandedSource = Util.replaceMacro(blobStoreEntry.sourceFile, envVars); - String expandedContainer = Util.replaceMacro(blobStoreEntry.container, envVars); - FilePath ws = build.getWorkspace(); - FilePath[] paths = ws.list(expandedSource); - String wsPath = ws.getRemote(); - - if (paths.length == 0) { - // try to do error diagnostics - log(listener.getLogger(), "No file(s) found: " + expandedSource); - String error = ws.validateAntFileMask(expandedSource); - if (error != null) - log(listener.getLogger(), error); - } - for (FilePath src : paths) { - String expandedPath = getDestinationPath(blobStoreEntry.path, blobStoreEntry.keepHierarchy, wsPath, src, envVars); - log(listener.getLogger(), "container=" + expandedContainer + ", path=" + expandedPath + ", file=" + src.getName()); - blobStoreProfile.upload(expandedContainer, expandedPath, src); - } - } - } catch (AuthorizationException e) { - LOGGER.severe("Failed to upload files to Blob Store due to authorization exception."); - RuntimeException overrideException = new RuntimeException("Failed to upload files to Blob Store due to authorization exception."); - overrideException.printStackTrace(listener.error("Failed to upload files")); - build.setResult(Result.UNSTABLE); - } catch (IOException e) { - LOGGER.severe("Failed to upload files to Blob Store: " + e.getMessage()); - e.printStackTrace(listener.error("Failed to upload files")); - build.setResult(Result.UNSTABLE); - } - - return true; - } - - private String getDestinationPath(String path, boolean appendFilePath, String wsPath, FilePath file, Map envVars) { - String resultPath; - String expandedPath = ""; - String relativeFilePath = ""; - String fileFullPath = file.getParent().getRemote(); - if (path != null && !path.equals("")) { - expandedPath = Util.replaceMacro(path, envVars); - if (expandedPath.endsWith("/")) { - expandedPath = expandedPath.substring(0, expandedPath.length() - 1); - } - } - if (appendFilePath && fileFullPath.startsWith(wsPath)) { - // Determine relative path to file relative to the workspace. - relativeFilePath = fileFullPath.substring(wsPath.length()); - if (relativeFilePath.startsWith("/")) { - relativeFilePath = relativeFilePath.substring(1); - } - } - if (!expandedPath.equals("") && !relativeFilePath.equals("")) { - resultPath = expandedPath + "/" + relativeFilePath; - } else { - resultPath = expandedPath + relativeFilePath; - } - - // Strip leading and trailing slashes to play nice with object stores. - if (resultPath.startsWith("/")) { - resultPath = resultPath.substring(1); - } - if (resultPath.endsWith("/")) { - resultPath = resultPath.substring(0, resultPath.length() - 1); - } - - return resultPath; - } - - /** - * @{see BuildStepMonitor#STEP} - * @return BuildStepMonitor.STEP - */ - public BuildStepMonitor getRequiredMonitorService() { - return BuildStepMonitor.STEP; - } - - /** - * {@see hudson.model.Descriptor} - */ - public static final class DescriptorImpl extends BuildStepDescriptor { - - private final CopyOnWriteList profiles = new CopyOnWriteList(); - private static final Logger LOGGER = Logger.getLogger(DescriptorImpl.class.getName()); - - public DescriptorImpl(Class clazz) { - super(clazz); - load(); - } - - public DescriptorImpl() { - this(BlobStorePublisher.class); - } - - @Override - public String getDisplayName() { - return "Publish artifacts to JClouds Clouds Storage "; - } - - @Override - public boolean configure(StaplerRequest req, net.sf.json.JSONObject json) throws FormException { - profiles.replaceBy(req.bindParametersToList(BlobStoreProfile.class, "jcblobstore.")); - save(); - return true; - } - - public BlobStoreProfile[] getProfiles() { - return profiles.toArray(new BlobStoreProfile[0]); - } - - public FormValidation doLoginCheck(final StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - String name = Util.fixEmpty(req.getParameter("name")); - if (name == null) {// name is not entered yet - return FormValidation.ok(); - } - BlobStoreProfile profile = new BlobStoreProfile(name, req.getParameter("providerName"), req.getParameter("identity"), - req.getParameter("credential")); - return FormValidation.ok(); - } - - @Override - public boolean isApplicable(Class aClass) { - return true; - } - - public ListBoxModel doFillProfileNameItems() { - ListBoxModel model = new ListBoxModel(); - for (BlobStoreProfile profile : getProfiles()) { - model.add(profile.getProfileName()); - } - return model; - } - } + private static final Logger LOGGER = Logger.getLogger(BlobStorePublisher.class.getName()); + + private String profileName; + @Extension + public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); + private final List entries; + + /** + * Create a new Blobstore publisher for the cofigured profile identified by profileName + * + * @param profileName - the name of the configured profile name + */ + @DataBoundConstructor + public BlobStorePublisher(String profileName, List entries) { + super(); + if (profileName == null) { + // defaults to the first one + BlobStoreProfile[] sites = DESCRIPTOR.getProfiles(); + if (sites.length > 0) + profileName = sites[0].getProfileName(); + } + this.entries = entries; + this.profileName = profileName; + } + + /** + * Get list of entries to be uploaded. + * + * @return + */ + public List getEntries() { + return entries; + } + + /** + * @return - current profile for a profileName or returns the first one if the profileName isn't configured + */ + public BlobStoreProfile getProfile() { + BlobStoreProfile[] profiles = DESCRIPTOR.getProfiles(); + + if (profileName == null && profiles.length > 0) + // default + return profiles[0]; + + for (BlobStoreProfile profile : profiles) { + if (profile.getProfileName().equals(profileName)) + return profile; + } + return null; + } + + public String getName() { + return this.profileName; + } + + public void setName(String profileName) { + this.profileName = profileName; + } + + protected void log(final PrintStream logger, final String message) { + logger.println(StringUtils.defaultString(getDescriptor().getDisplayName()) + " " + message); + } + + /** + * Perform the build step of uploading the configured file entries to the blobstore. + *

+ *

    + *
  • If the build result is failure, will not do anything except logging the stuff.
  • + *
  • If the blobstore profile isn't configured, or the uploading failed, the build is set to be unstable.
  • + *
  • If the upload is succesful, the build is set to be stable.
  • + *
+ * + * @param build - reference to curerent build. + * @param launcher - {@link Launcher} + * @param listener - {@link BuildListener} + * @return Always returns to indicate that build can continue, so we won't block other steps. + * @throws InterruptedException + * @throws IOException + */ + @Override + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + + if (build.getResult() == Result.FAILURE) { + // build failed. don't post + LOGGER.info("Build failed, not publishing any files to blobstore"); + return true; + } + BlobStoreProfile blobStoreProfile = getProfile(); + if (blobStoreProfile == null) { + log(listener.getLogger(), "No JClouds Blob Store blobStoreProfile is configured."); + build.setResult(Result.UNSTABLE); + return true; + } + log(listener.getLogger(), "Using JClouds blobStoreProfile: " + blobStoreProfile.getProfileName()); + try { + Map envVars = build.getEnvironment(listener); + + for (BlobStoreEntry blobStoreEntry : entries) { + String expandedSource = Util.replaceMacro(blobStoreEntry.sourceFile, envVars); + String expandedContainer = Util.replaceMacro(blobStoreEntry.container, envVars); + FilePath ws = build.getWorkspace(); + FilePath[] paths = ws.list(expandedSource); + String wsPath = ws.getRemote(); + + if (paths.length == 0) { + // try to do error diagnostics + log(listener.getLogger(), "No file(s) found: " + expandedSource); + String error = ws.validateAntFileMask(expandedSource); + if (error != null) + log(listener.getLogger(), error); + } + for (FilePath src : paths) { + String expandedPath = getDestinationPath(blobStoreEntry.path, blobStoreEntry.keepHierarchy, wsPath, src, envVars); + log(listener.getLogger(), "container=" + expandedContainer + ", path=" + expandedPath + ", file=" + src.getName()); + blobStoreProfile.upload(expandedContainer, expandedPath, src); + } + } + } catch (AuthorizationException e) { + LOGGER.severe("Failed to upload files to Blob Store due to authorization exception."); + RuntimeException overrideException = new RuntimeException("Failed to upload files to Blob Store due to authorization exception."); + overrideException.printStackTrace(listener.error("Failed to upload files")); + build.setResult(Result.UNSTABLE); + } catch (IOException e) { + LOGGER.severe("Failed to upload files to Blob Store: " + e.getMessage()); + e.printStackTrace(listener.error("Failed to upload files")); + build.setResult(Result.UNSTABLE); + } + + return true; + } + + private String getDestinationPath(String path, boolean appendFilePath, String wsPath, FilePath file, Map envVars) { + String resultPath; + String expandedPath = ""; + String relativeFilePath = ""; + String fileFullPath = file.getParent().getRemote(); + if (path != null && !path.equals("")) { + expandedPath = Util.replaceMacro(path, envVars); + if (expandedPath.endsWith("/")) { + expandedPath = expandedPath.substring(0, expandedPath.length() - 1); + } + } + if (appendFilePath && fileFullPath.startsWith(wsPath)) { + // Determine relative path to file relative to the workspace. + relativeFilePath = fileFullPath.substring(wsPath.length()); + if (relativeFilePath.startsWith("/")) { + relativeFilePath = relativeFilePath.substring(1); + } + } + if (!expandedPath.equals("") && !relativeFilePath.equals("")) { + resultPath = expandedPath + "/" + relativeFilePath; + } else { + resultPath = expandedPath + relativeFilePath; + } + + // Strip leading and trailing slashes to play nice with object stores. + if (resultPath.startsWith("/")) { + resultPath = resultPath.substring(1); + } + if (resultPath.endsWith("/")) { + resultPath = resultPath.substring(0, resultPath.length() - 1); + } + + return resultPath; + } + + /** + * @return BuildStepMonitor.STEP + * @{see BuildStepMonitor#STEP} + */ + public BuildStepMonitor getRequiredMonitorService() { + return BuildStepMonitor.STEP; + } + + /** + * {@see hudson.model.Descriptor} + */ + public static final class DescriptorImpl extends BuildStepDescriptor { + + private final CopyOnWriteList profiles = new CopyOnWriteList(); + private static final Logger LOGGER = Logger.getLogger(DescriptorImpl.class.getName()); + + public DescriptorImpl(Class clazz) { + super(clazz); + load(); + } + + public DescriptorImpl() { + this(BlobStorePublisher.class); + } + + @Override + public String getDisplayName() { + return "Publish artifacts to JClouds Clouds Storage "; + } + + @Override + public boolean configure(StaplerRequest req, net.sf.json.JSONObject json) throws FormException { + profiles.replaceBy(req.bindParametersToList(BlobStoreProfile.class, "jcblobstore.")); + save(); + return true; + } + + public BlobStoreProfile[] getProfiles() { + return profiles.toArray(new BlobStoreProfile[0]); + } + + public FormValidation doLoginCheck(final StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + String name = Util.fixEmpty(req.getParameter("name")); + if (name == null) {// name is not entered yet + return FormValidation.ok(); + } + BlobStoreProfile profile = new BlobStoreProfile(name, req.getParameter("providerName"), req.getParameter("identity"), + req.getParameter("credential")); + return FormValidation.ok(); + } + + @Override + public boolean isApplicable(Class aClass) { + return true; + } + + public ListBoxModel doFillProfileNameItems() { + ListBoxModel model = new ListBoxModel(); + for (BlobStoreProfile profile : getProfiles()) { + model.add(profile.getProfileName()); + } + return model; + } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/ComputeLogger.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/ComputeLogger.java index 1d2844ca..81c4f5b5 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/ComputeLogger.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/ComputeLogger.java @@ -4,33 +4,33 @@ /** * bumps {@code jclouds.compute} logging category debug to info. - * + * * @author Adrian Cole */ class ComputeLogger extends org.jclouds.logging.jdk.JDKLogger { - public static class Factory extends JDKLoggerFactory { - public org.jclouds.logging.Logger getLogger(String category) { - if (category.equals("jclouds.compute") || (category.equals("jclouds.wire") && wireLogging)) - return new ComputeLogger(Logger.getLogger(category)); - else - return super.getLogger(category); - } - } + public static class Factory extends JDKLoggerFactory { + public org.jclouds.logging.Logger getLogger(String category) { + if (category.equals("jclouds.compute") || (category.equals("jclouds.wire") && wireLogging)) + return new ComputeLogger(Logger.getLogger(category)); + else + return super.getLogger(category); + } + } - public ComputeLogger(Logger logger) { - super(logger); - } + public ComputeLogger(Logger logger) { + super(logger); + } - @Override - public boolean isDebugEnabled() { - return true; - } + @Override + public boolean isDebugEnabled() { + return true; + } - @Override - protected void logDebug(String message) { - super.logInfo(message); - } + @Override + protected void logDebug(String message) { + super.logInfo(message); + } - public static boolean wireLogging = Boolean.getBoolean(ComputeLogger.class.getName() + ".wireLogging"); -} \ No newline at end of file + public static boolean wireLogging = Boolean.getBoolean(ComputeLogger.class.getName() + ".wireLogging"); +} diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/InstancesToRun.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/InstancesToRun.java index 1d31cd17..b3e64306 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/InstancesToRun.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/InstancesToRun.java @@ -16,66 +16,66 @@ import org.kohsuke.stapler.export.ExportedBean; public final class InstancesToRun extends AbstractDescribableImpl { - public final String cloudName; - public final String templateName; - public final String manualTemplateName; - public final int count; - public final boolean suspendOrTerminate; + public final String cloudName; + public final String templateName; + public final String manualTemplateName; + public final int count; + public final boolean suspendOrTerminate; - @DataBoundConstructor - public InstancesToRun(String cloudName, String templateName, String manualTemplateName, int count, boolean suspendOrTerminate) { - this.cloudName = Util.fixEmptyAndTrim(cloudName); - this.templateName = Util.fixEmptyAndTrim(templateName); - this.manualTemplateName = Util.fixEmptyAndTrim(manualTemplateName); - this.count = count; - this.suspendOrTerminate = suspendOrTerminate; - } + @DataBoundConstructor + public InstancesToRun(String cloudName, String templateName, String manualTemplateName, int count, boolean suspendOrTerminate) { + this.cloudName = Util.fixEmptyAndTrim(cloudName); + this.templateName = Util.fixEmptyAndTrim(templateName); + this.manualTemplateName = Util.fixEmptyAndTrim(manualTemplateName); + this.count = count; + this.suspendOrTerminate = suspendOrTerminate; + } - public String getActualTemplateName() { - if (isUsingManualTemplateName()) { - return manualTemplateName; - } else { - return templateName; - } - } + public String getActualTemplateName() { + if (isUsingManualTemplateName()) { + return manualTemplateName; + } else { + return templateName; + } + } - public boolean isUsingManualTemplateName() { - if (manualTemplateName == null || manualTemplateName.equals("")) { - return false; - } else { - return true; - } - } + public boolean isUsingManualTemplateName() { + if (manualTemplateName == null || manualTemplateName.equals("")) { + return false; + } else { + return true; + } + } - @Extension - public static class DescriptorImpl extends Descriptor { - public ListBoxModel doFillCloudNameItems() { - ListBoxModel m = new ListBoxModel(); - for (String cloudName : JCloudsCloud.getCloudNames()) { - m.add(cloudName, cloudName); - } + @Extension + public static class DescriptorImpl extends Descriptor { + public ListBoxModel doFillCloudNameItems() { + ListBoxModel m = new ListBoxModel(); + for (String cloudName : JCloudsCloud.getCloudNames()) { + m.add(cloudName, cloudName); + } - return m; - } + return m; + } - public ListBoxModel doFillTemplateNameItems(@QueryParameter String cloudName) { - ListBoxModel m = new ListBoxModel(); - JCloudsCloud c = JCloudsCloud.getByName(cloudName); - if (c != null) { - for (JCloudsSlaveTemplate t : c.getTemplates()) { - m.add(String.format("%s in cloud %s", t.name, cloudName), t.name); - } - } - return m; - } + public ListBoxModel doFillTemplateNameItems(@QueryParameter String cloudName) { + ListBoxModel m = new ListBoxModel(); + JCloudsCloud c = JCloudsCloud.getByName(cloudName); + if (c != null) { + for (JCloudsSlaveTemplate t : c.getTemplates()) { + m.add(String.format("%s in cloud %s", t.name, cloudName), t.name); + } + } + return m; + } - public FormValidation doCheckCount(@QueryParameter String value) { - return FormValidation.validatePositiveInteger(value); - } + public FormValidation doCheckCount(@QueryParameter String value) { + return FormValidation.validatePositiveInteger(value); + } - @Override - public String getDisplayName() { - return ""; - } - } -} \ No newline at end of file + @Override + public String getDisplayName() { + return ""; + } + } +} diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsBuildWrapper.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsBuildWrapper.java index 6f3e2eba..8341a3a0 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsBuildWrapper.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsBuildWrapper.java @@ -38,108 +38,108 @@ import shaded.com.google.common.util.concurrent.MoreExecutors; public class JCloudsBuildWrapper extends BuildWrapper { - private final List instancesToRun; - - @DataBoundConstructor - public JCloudsBuildWrapper(List instancesToRun) { - this.instancesToRun = instancesToRun; - } - - public List getInstancesToRun() { - return instancesToRun; - } - - // - // convert Jenkins staticy stuff into pojos; performing as little critical stuff here as - // possible, as this method is very hard to test due to static usage, etc. - // - @Override - public Environment setUp(final AbstractBuild build, Launcher launcher, final BuildListener listener) { - // TODO: on shutdown, close all - final LoadingCache computeCache = CacheBuilder.newBuilder().build(new CacheLoader() { - - @Override - public ComputeService load(String arg0) throws Exception { - return JCloudsCloud.getByName(arg0).getCompute(); - } - - }); - // final ParametersAction parameters = build.getAction(ParametersAction.class); - - // eagerly lookup node supplier so that errors occur before we attempt to provision things - Iterable nodePlans = Iterables.transform(instancesToRun, new Function() { - - public NodePlan apply(InstancesToRun instance) { - String cloudName = instance.cloudName; - String templateName = Util.replaceMacro(instance.getActualTemplateName(), build.getBuildVariableResolver()); - // String templateName = getParameterString(parameters, instance.getActualTemplateName(), build); - Supplier nodeSupplier = JCloudsCloud.getByName(cloudName).getTemplate(templateName); - // take the hit here, as opposed to later - computeCache.getUnchecked(cloudName); - return new NodePlan(cloudName, templateName, instance.count, instance.suspendOrTerminate, nodeSupplier); - } - - }); - - // converting to a logger as it is an interface and easier to test - final Logger logger = new BuildListenerLogger(listener); - - final TerminateNodes terminateNodes = new TerminateNodes(logger, computeCache); - - ProvisionPlannedInstancesAndDestroyAllOnError provisioner = new ProvisionPlannedInstancesAndDestroyAllOnError( - MoreExecutors.listeningDecorator(Computer.threadPoolForRemoting), logger, terminateNodes); - - final Iterable runningNode = provisioner.apply(nodePlans); - - return new Environment() { - @Override - public void buildEnvVars(Map env) { - List ips = getInstanceIPs(runningNode, listener.getLogger()); - env.put("JCLOUDS_IPS", Util.join(ips, ",")); - } - - @Override - public boolean tearDown(AbstractBuild build, final BuildListener listener) throws IOException, InterruptedException { - terminateNodes.apply(runningNode); - return true; - } - - }; - - } - - public List getInstanceIPs(Iterable runningNodes, PrintStream logger) { - Builder ips = ImmutableList. builder(); - - for (RunningNode runningNode : runningNodes) { - String[] possibleIPs = JCloudsLauncher.getConnectionAddresses(runningNode.getNode(), logger); - if (possibleIPs[0] != null) { - ips.add(possibleIPs[0]); - } - } - - return ips.build(); - } - - private String getParameterString(ParametersAction parameters, String original, AbstractBuild build) { - if (parameters != null) { - original = parameters.substitute(build, original); - } - - return original; - } - - @Extension - public static final class DescriptorImpl extends BuildWrapperDescriptor { - @Override - public String getDisplayName() { - return "JClouds Instance Creation"; - } - - @Override - public boolean isApplicable(AbstractProject item) { - return true; - } - - } + private final List instancesToRun; + + @DataBoundConstructor + public JCloudsBuildWrapper(List instancesToRun) { + this.instancesToRun = instancesToRun; + } + + public List getInstancesToRun() { + return instancesToRun; + } + + // + // convert Jenkins staticy stuff into pojos; performing as little critical stuff here as + // possible, as this method is very hard to test due to static usage, etc. + // + @Override + public Environment setUp(final AbstractBuild build, Launcher launcher, final BuildListener listener) { + // TODO: on shutdown, close all + final LoadingCache computeCache = CacheBuilder.newBuilder().build(new CacheLoader() { + + @Override + public ComputeService load(String arg0) throws Exception { + return JCloudsCloud.getByName(arg0).getCompute(); + } + + }); + // final ParametersAction parameters = build.getAction(ParametersAction.class); + + // eagerly lookup node supplier so that errors occur before we attempt to provision things + Iterable nodePlans = Iterables.transform(instancesToRun, new Function() { + + public NodePlan apply(InstancesToRun instance) { + String cloudName = instance.cloudName; + String templateName = Util.replaceMacro(instance.getActualTemplateName(), build.getBuildVariableResolver()); + // String templateName = getParameterString(parameters, instance.getActualTemplateName(), build); + Supplier nodeSupplier = JCloudsCloud.getByName(cloudName).getTemplate(templateName); + // take the hit here, as opposed to later + computeCache.getUnchecked(cloudName); + return new NodePlan(cloudName, templateName, instance.count, instance.suspendOrTerminate, nodeSupplier); + } + + }); + + // converting to a logger as it is an interface and easier to test + final Logger logger = new BuildListenerLogger(listener); + + final TerminateNodes terminateNodes = new TerminateNodes(logger, computeCache); + + ProvisionPlannedInstancesAndDestroyAllOnError provisioner = new ProvisionPlannedInstancesAndDestroyAllOnError( + MoreExecutors.listeningDecorator(Computer.threadPoolForRemoting), logger, terminateNodes); + + final Iterable runningNode = provisioner.apply(nodePlans); + + return new Environment() { + @Override + public void buildEnvVars(Map env) { + List ips = getInstanceIPs(runningNode, listener.getLogger()); + env.put("JCLOUDS_IPS", Util.join(ips, ",")); + } + + @Override + public boolean tearDown(AbstractBuild build, final BuildListener listener) throws IOException, InterruptedException { + terminateNodes.apply(runningNode); + return true; + } + + }; + + } + + public List getInstanceIPs(Iterable runningNodes, PrintStream logger) { + Builder ips = ImmutableList.builder(); + + for (RunningNode runningNode : runningNodes) { + String[] possibleIPs = JCloudsLauncher.getConnectionAddresses(runningNode.getNode(), logger); + if (possibleIPs[0] != null) { + ips.add(possibleIPs[0]); + } + } + + return ips.build(); + } + + private String getParameterString(ParametersAction parameters, String original, AbstractBuild build) { + if (parameters != null) { + original = parameters.substitute(build, original); + } + + return original; + } + + @Extension + public static final class DescriptorImpl extends BuildWrapperDescriptor { + @Override + public String getDisplayName() { + return "JClouds Instance Creation"; + } + + @Override + public boolean isApplicable(AbstractProject item) { + return true; + } + + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCleanupThread.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCleanupThread.java index 812b3668..09aa2435 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCleanupThread.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCleanupThread.java @@ -17,62 +17,62 @@ @Extension public final class JCloudsCleanupThread extends AsyncPeriodicWork { - public JCloudsCleanupThread() { - super("JClouds slave cleanup"); - } + public JCloudsCleanupThread() { + super("JClouds slave cleanup"); + } - @Override - public long getRecurrencePeriod() { - return MIN * 5; - } + @Override + public long getRecurrencePeriod() { + return MIN * 5; + } - public static void invoke() { - getInstance().run(); - } + public static void invoke() { + getInstance().run(); + } - private static JCloudsCleanupThread getInstance() { - return Jenkins.getInstance().getExtensionList(AsyncPeriodicWork.class).get(JCloudsCleanupThread.class); - } + private static JCloudsCleanupThread getInstance() { + return Jenkins.getInstance().getExtensionList(AsyncPeriodicWork.class).get(JCloudsCleanupThread.class); + } - @Override - protected void execute(TaskListener listener) { - final ImmutableList.Builder> deletedNodesBuilder = ImmutableList.> builder(); - ListeningExecutorService executor = MoreExecutors.listeningDecorator(Computer.threadPoolForRemoting); + @Override + protected void execute(TaskListener listener) { + final ImmutableList.Builder> deletedNodesBuilder = ImmutableList.>builder(); + ListeningExecutorService executor = MoreExecutors.listeningDecorator(Computer.threadPoolForRemoting); final ImmutableList.Builder computersToDeleteBuilder = ImmutableList.builder(); - for (final Computer c : Jenkins.getInstance().getComputers()) { - if (JCloudsComputer.class.isInstance(c)) { - if (((JCloudsComputer) c).getNode().isPendingDelete()) { + for (final Computer c : Jenkins.getInstance().getComputers()) { + if (JCloudsComputer.class.isInstance(c)) { + if (((JCloudsComputer) c).getNode().isPendingDelete()) { final JCloudsComputer comp = (JCloudsComputer) c; computersToDeleteBuilder.add(comp); - ListenableFuture f = executor.submit(new Runnable() { - public void run() { - logger.log(Level.INFO, "Deleting pending node " + comp.getName()); - try { + ListenableFuture f = executor.submit(new Runnable() { + public void run() { + logger.log(Level.INFO, "Deleting pending node " + comp.getName()); + try { comp.getNode().terminate(); - } catch (IOException e) { + } catch (IOException e) { logger.log(Level.WARNING, "Failed to disconnect and delete " + c.getName() + ": " + e.getMessage()); } catch (InterruptedException e) { - logger.log(Level.WARNING, "Failed to disconnect and delete " + c.getName() + ": " + e.getMessage()); - } - } - }); - deletedNodesBuilder.add(f); - } - } - } + logger.log(Level.WARNING, "Failed to disconnect and delete " + c.getName() + ": " + e.getMessage()); + } + } + }); + deletedNodesBuilder.add(f); + } + } + } - Futures.getUnchecked(Futures.successfulAsList(deletedNodesBuilder.build())); + Futures.getUnchecked(Futures.successfulAsList(deletedNodesBuilder.build())); for (JCloudsComputer c : computersToDeleteBuilder.build()) { try { c.deleteSlave(); } catch (IOException e) { - logger.log(Level.WARNING, "Failed to disconnect and delete "+c.getName()+": "+e.getMessage()); + logger.log(Level.WARNING, "Failed to disconnect and delete " + c.getName() + ": " + e.getMessage()); } catch (InterruptedException e) { - logger.log(Level.WARNING, "Failed to disconnect and delete "+c.getName()+": "+e.getMessage()); + logger.log(Level.WARNING, "Failed to disconnect and delete " + c.getName() + ": " + e.getMessage()); } } - } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCloud.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCloud.java index 975fed83..a49d66c8 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCloud.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsCloud.java @@ -61,410 +61,407 @@ /** * The JClouds version of the Jenkins Cloud. - * + * * @author Vijay Kiran */ public class JCloudsCloud extends Cloud { - static final Logger LOGGER = Logger.getLogger(JCloudsCloud.class.getName()); - - public final String identity; - public final Secret credential; - public final String providerName; - - public final String privateKey; - public final String publicKey; - public final String endPointUrl; - public final String profile; - private final int retentionTime; - public int instanceCap; - public final List templates; - public final int scriptTimeout; - public final int startTimeout; - private transient ComputeService compute; - public final String zones; - - public static List getCloudNames() { - List cloudNames = new ArrayList(); - for (Cloud c : Hudson.getInstance().clouds) { - if (JCloudsCloud.class.isInstance(c)) { - cloudNames.add(c.name); - } - } - - return cloudNames; - } - - public static JCloudsCloud getByName(String name) { - return (JCloudsCloud) Hudson.getInstance().clouds.getByName(name); - } - - @DataBoundConstructor - public JCloudsCloud(final String profile, final String providerName, final String identity, final String credential, final String privateKey, - final String publicKey, final String endPointUrl, final int instanceCap, final int retentionTime, final int scriptTimeout, final int startTimeout, - final String zones, final List templates) { - super(Util.fixEmptyAndTrim(profile)); - this.profile = Util.fixEmptyAndTrim(profile); - this.providerName = Util.fixEmptyAndTrim(providerName); - this.identity = Util.fixEmptyAndTrim(identity); - this.credential = Secret.fromString(credential); - this.privateKey = privateKey; - this.publicKey = publicKey; - this.endPointUrl = Util.fixEmptyAndTrim(endPointUrl); - this.instanceCap = instanceCap; - this.retentionTime = retentionTime; - this.scriptTimeout = scriptTimeout; - this.startTimeout = startTimeout; - this.templates = Objects.firstNonNull(templates, Collections. emptyList()); - this.zones = Util.fixEmptyAndTrim(zones); - readResolve(); - } - - protected Object readResolve() { - for (JCloudsSlaveTemplate template : templates) - template.cloud = this; - return this; - } - - /** - * Get the retention time, defaulting to 30 minutes. - */ - public int getRetentionTime() { - if (retentionTime == 0) { - return 30; - } else { - return retentionTime; - } - } - - static final Iterable MODULES = ImmutableSet. of(new SshjSshClientModule(), new JDKLoggingModule() { - @Override - public org.jclouds.logging.Logger.LoggerFactory createLoggerFactory() { - return new ComputeLogger.Factory(); - } - }, new EnterpriseConfigurationModule()); - - static ComputeServiceContext ctx(String providerName, String identity, String credential, String endPointUrl, String zones) { - Properties overrides = new Properties(); - if (!Strings.isNullOrEmpty(endPointUrl)) { - overrides.setProperty(Constants.PROPERTY_ENDPOINT, endPointUrl); - } - return ctx(providerName, identity, credential, overrides, zones); - } - - static ComputeServiceContext ctx(String providerName, String identity, String credential, Properties overrides, String zones) { - if (!Strings.isNullOrEmpty(zones)) { - overrides.setProperty(LocationConstants.PROPERTY_ZONES, zones); - } - // correct the classloader so that extensions can be found - Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); - return ContextBuilder.newBuilder(providerName).credentials(identity, credential).overrides(overrides).modules(MODULES) - .buildView(ComputeServiceContext.class); - } - - public ComputeService getCompute() { - if (this.compute == null) { - Properties overrides = new Properties(); - if (!Strings.isNullOrEmpty(this.endPointUrl)) { - overrides.setProperty(Constants.PROPERTY_ENDPOINT, this.endPointUrl); - } - if (scriptTimeout > 0) { - overrides.setProperty(ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE, String.valueOf(scriptTimeout)); - } - if (startTimeout > 0) { - overrides.setProperty(ComputeServiceProperties.TIMEOUT_NODE_RUNNING, String.valueOf(startTimeout)); - } - this.compute = ctx(this.providerName, this.identity, Secret.toString(credential), overrides, this.zones).getComputeService(); - } - return compute; - } - - public List getTemplates() { - return Collections.unmodifiableList(templates); - } - - /** - * {@inheritDoc} - */ - @Override - public Collection provision(Label label, int excessWorkload) { - final JCloudsSlaveTemplate t = getTemplate(label); - - List r = new ArrayList(); - while (excessWorkload > 0 + static final Logger LOGGER = Logger.getLogger(JCloudsCloud.class.getName()); + + public final String identity; + public final Secret credential; + public final String providerName; + + public final String privateKey; + public final String publicKey; + public final String endPointUrl; + public final String profile; + private final int retentionTime; + public int instanceCap; + public final List templates; + public final int scriptTimeout; + public final int startTimeout; + private transient ComputeService compute; + public final String zones; + + public static List getCloudNames() { + List cloudNames = new ArrayList(); + for (Cloud c : Hudson.getInstance().clouds) { + if (JCloudsCloud.class.isInstance(c)) { + cloudNames.add(c.name); + } + } + + return cloudNames; + } + + public static JCloudsCloud getByName(String name) { + return (JCloudsCloud) Hudson.getInstance().clouds.getByName(name); + } + + @DataBoundConstructor + public JCloudsCloud(final String profile, final String providerName, final String identity, final String credential, final String privateKey, + final String publicKey, final String endPointUrl, final int instanceCap, final int retentionTime, final int scriptTimeout, final int startTimeout, + final String zones, final List templates) { + super(Util.fixEmptyAndTrim(profile)); + this.profile = Util.fixEmptyAndTrim(profile); + this.providerName = Util.fixEmptyAndTrim(providerName); + this.identity = Util.fixEmptyAndTrim(identity); + this.credential = Secret.fromString(credential); + this.privateKey = privateKey; + this.publicKey = publicKey; + this.endPointUrl = Util.fixEmptyAndTrim(endPointUrl); + this.instanceCap = instanceCap; + this.retentionTime = retentionTime; + this.scriptTimeout = scriptTimeout; + this.startTimeout = startTimeout; + this.templates = Objects.firstNonNull(templates, Collections.emptyList()); + this.zones = Util.fixEmptyAndTrim(zones); + readResolve(); + } + + protected Object readResolve() { + for (JCloudsSlaveTemplate template : templates) + template.cloud = this; + return this; + } + + /** + * Get the retention time, defaulting to 30 minutes. + */ + public int getRetentionTime() { + if (retentionTime == 0) { + return 30; + } else { + return retentionTime; + } + } + + static final Iterable MODULES = ImmutableSet.of(new SshjSshClientModule(), new JDKLoggingModule() { + @Override + public org.jclouds.logging.Logger.LoggerFactory createLoggerFactory() { + return new ComputeLogger.Factory(); + } + }, new EnterpriseConfigurationModule()); + + static ComputeServiceContext ctx(String providerName, String identity, String credential, String endPointUrl, String zones) { + Properties overrides = new Properties(); + if (!Strings.isNullOrEmpty(endPointUrl)) { + overrides.setProperty(Constants.PROPERTY_ENDPOINT, endPointUrl); + } + return ctx(providerName, identity, credential, overrides, zones); + } + + static ComputeServiceContext ctx(String providerName, String identity, String credential, Properties overrides, String zones) { + if (!Strings.isNullOrEmpty(zones)) { + overrides.setProperty(LocationConstants.PROPERTY_ZONES, zones); + } + // correct the classloader so that extensions can be found + Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); + return ContextBuilder.newBuilder(providerName).credentials(identity, credential).overrides(overrides).modules(MODULES) + .buildView(ComputeServiceContext.class); + } + + public ComputeService getCompute() { + if (this.compute == null) { + Properties overrides = new Properties(); + if (!Strings.isNullOrEmpty(this.endPointUrl)) { + overrides.setProperty(Constants.PROPERTY_ENDPOINT, this.endPointUrl); + } + if (scriptTimeout > 0) { + overrides.setProperty(ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE, String.valueOf(scriptTimeout)); + } + if (startTimeout > 0) { + overrides.setProperty(ComputeServiceProperties.TIMEOUT_NODE_RUNNING, String.valueOf(startTimeout)); + } + this.compute = ctx(this.providerName, this.identity, Secret.toString(credential), overrides, this.zones).getComputeService(); + } + return compute; + } + + public List getTemplates() { + return Collections.unmodifiableList(templates); + } + + /** + * {@inheritDoc} + */ + @Override + public Collection provision(Label label, int excessWorkload) { + final JCloudsSlaveTemplate t = getTemplate(label); + + List r = new ArrayList(); + while (excessWorkload > 0 && !Jenkins.getInstance().isQuietingDown() && !Jenkins.getInstance().isTerminating()) { - if ((getRunningNodesCount() + r.size()) >= instanceCap) { - LOGGER.info("Instance cap reached while adding capacity for label " + ((label != null) ? label.toString() : "null")); - break; // maxed out - } - - r.add(new PlannedNode(t.name, Computer.threadPoolForRemoting.submit(new Callable() { - public Node call() throws Exception { - // TODO: record the output somewhere - JCloudsSlave s = t.provisionSlave(new StreamTaskListener(System.out)); - Hudson.getInstance().addNode(s); - // Cloud instances may have a long init script. If - // we declare - // the provisioning complete by returning without - // the connect - // operation, NodeProvisioner may decide that it - // still wants - // one more instance, because it sees that (1) all - // the slaves - // are offline (because it's still being launched) - // and - // (2) there's no capacity provisioned yet. - // - // deferring the completion of provisioning until - // the launch - // goes successful prevents this problem. - s.toComputer().connect(false).get(); - return s; - } - }), Util.tryParseNumber(t.numExecutors, 1).intValue())); - excessWorkload -= t.getNumExecutors(); - } - return r; - } - - @Override - public boolean canProvision(final Label label) { - return getTemplate(label) != null; - } - - public JCloudsSlaveTemplate getTemplate(String name) { - for (JCloudsSlaveTemplate t : templates) - if (t.name.equals(name)) - return t; - return null; - } - - /** - * Gets {@link jenkins.plugins.jclouds.compute.JCloudsSlaveTemplate} that has the matching {@link Label}. - */ - public JCloudsSlaveTemplate getTemplate(Label label) { - for (JCloudsSlaveTemplate t : templates) - if (label == null || label.matches(t.getLabelSet())) - return t; - return null; - } - - /** - * Provisions a new node manually (by clicking a button in the computer list) - * - * @param req - * {@link StaplerRequest} - * @param rsp - * {@link StaplerResponse} - * @param name - * Name of the template to provision - * @throws ServletException - * @throws IOException - * @throws Descriptor.FormException - */ - public void doProvision(StaplerRequest req, StaplerResponse rsp, @QueryParameter String name) throws ServletException, IOException, - Descriptor.FormException { - checkPermission(PROVISION); - if (name == null) { - sendError("The slave template name query parameter is missing", req, rsp); - return; - } - JCloudsSlaveTemplate t = getTemplate(name); - if (t == null) { - sendError("No such slave template with name : " + name, req, rsp); - return; - } - - if (getRunningNodesCount() < instanceCap) { - StringWriter sw = new StringWriter(); - StreamTaskListener listener = new StreamTaskListener(sw); - JCloudsSlave node = t.provisionSlave(listener); - Hudson.getInstance().addNode(node); - rsp.sendRedirect2(req.getContextPath() + "/computer/" + node.getNodeName()); - } else { - sendError("Instance cap for this cloud is now reached for cloud profile: " + profile + " for template type " + name, req, rsp); - } - } - - /** - * Determine how many nodes are currently running for this cloud. - */ - public int getRunningNodesCount() { - int nodeCount = 0; - - for (ComputeMetadata cm : getCompute().listNodes()) { - if (NodeMetadata.class.isInstance(cm)) { - String nodeGroup = ((NodeMetadata) cm).getGroup(); - - if (getTemplate(nodeGroup) != null && !((NodeMetadata) cm).getStatus().equals(NodeMetadata.Status.SUSPENDED) - && !((NodeMetadata) cm).getStatus().equals(NodeMetadata.Status.TERMINATED)) { - nodeCount++; - } - } - } - return nodeCount; - } - - @Extension - public static class DescriptorImpl extends Descriptor { - - /** - * Human readable name of this kind of configurable object. - */ - @Override - public String getDisplayName() { - return "Cloud (JClouds)"; - } - - public FormValidation doTestConnection(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, - @QueryParameter String privateKey, @QueryParameter String endPointUrl, @QueryParameter String zones) throws IOException { - if (identity == null) - return FormValidation.error("Invalid (AccessId)."); - if (credential == null) - return FormValidation.error("Invalid credential (secret key)."); - if (privateKey == null) - return FormValidation.error("Private key is not specified. Click 'Generate Key' to generate one."); - - // Remove empty text/whitespace from the fields. - providerName = Util.fixEmptyAndTrim(providerName); - identity = Util.fixEmptyAndTrim(identity); - credential = Secret.fromString(credential).getPlainText(); - endPointUrl = Util.fixEmptyAndTrim(endPointUrl); - zones = Util.fixEmptyAndTrim(zones); - - FormValidation result = FormValidation.ok("Connection succeeded!"); - ComputeServiceContext ctx = null; - try { - Properties overrides = new Properties(); - if (!Strings.isNullOrEmpty(endPointUrl)) { - overrides.setProperty(Constants.PROPERTY_ENDPOINT, endPointUrl); - } - - ctx = ctx(providerName, identity, credential, overrides, zones); - - ctx.getComputeService().listNodes(); - } catch (Exception ex) { - result = FormValidation.error("Cannot connect to specified cloud, please check the identity and credentials: " + ex.getMessage()); - } finally { - Closeables.close(ctx,true); - } - return result; - } - - public FormValidation doGenerateKeyPair(StaplerResponse rsp, String identity, String credential) throws IOException, ServletException { - Map keyPair = SshKeys.generate(); - rsp.addHeader("script", "findPreviousFormItem(button,'privateKey').value='" + keyPair.get("private").replace("\n", "\\n") + "';" - + "findPreviousFormItem(button,'publicKey').value='" + keyPair.get("public").replace("\n", "\\n") + "';"); - return FormValidation.ok("Successfully generated private Key!"); - } - - public FormValidation doCheckPrivateKey(@QueryParameter String value) throws IOException, ServletException { - boolean hasStart = false, hasEnd = false; - BufferedReader br = new BufferedReader(new StringReader(value)); - String line; - while ((line = br.readLine()) != null) { - if (line.equals("-----BEGIN RSA PRIVATE KEY-----")) - hasStart = true; - if (line.equals("-----END RSA PRIVATE KEY-----")) - hasEnd = true; - } - if (!hasStart) - return FormValidation.error("Please make sure that the private key starts with '-----BEGIN RSA PRIVATE KEY-----'"); - if (!hasEnd) - return FormValidation.error("The private key is missing the trailing 'END RSA PRIVATE KEY' marker. Copy&paste error?"); - if (SshKeys.fingerprintPrivateKey(value) == null) - return FormValidation.error("Invalid private key, please check again or click on 'Generate Key' to generate a new key"); - return FormValidation.ok(); - } - - public ListBoxModel doFillProviderNameItems() { - ListBoxModel m = new ListBoxModel(); - - // correct the classloader so that extensions can be found - Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); - // TODO: apis need endpoints, providers don't; do something smarter - // with this stuff :) - Builder builder = ImmutableSet. builder(); - builder.addAll(Iterables.transform(Apis.viewableAs(ComputeServiceContext.class), Apis.idFunction())); - builder.addAll(Iterables.transform(Providers.viewableAs(ComputeServiceContext.class), Providers.idFunction())); - Iterable supportedProviders = ImmutableSortedSet.copyOf(builder.build()); - - for (String supportedProvider : supportedProviders) { - m.add(supportedProvider, supportedProvider); - } - return m; - } - - public AutoCompletionCandidates doAutoCompleteProviderName(@QueryParameter final String value) { - // correct the classloader so that extensions can be found - Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); - // TODO: apis need endpoints, providers don't; do something smarter - // with this stuff :) - Builder builder = ImmutableSet. builder(); - builder.addAll(Iterables.transform(Apis.viewableAs(ComputeServiceContext.class), Apis.idFunction())); - builder.addAll(Iterables.transform(Providers.viewableAs(ComputeServiceContext.class), Providers.idFunction())); - Iterable supportedProviders = builder.build(); - - Iterable matchedProviders = Iterables.filter(supportedProviders, new Predicate() { - public boolean apply(@Nullable String input) { - return input != null && input.startsWith(value.toLowerCase()); - } - }); - - AutoCompletionCandidates candidates = new AutoCompletionCandidates(); - for (String matchedProvider : matchedProviders) { - candidates.add(matchedProvider); - } - return candidates; - } - - public FormValidation doCheckProfile(@QueryParameter String value) { - return FormValidation.validateRequired(value); - } - - public FormValidation doCheckProviderName(@QueryParameter String value) { - return FormValidation.validateRequired(value); - } - - public FormValidation doCheckPublicKey(@QueryParameter String value) { - return FormValidation.validateRequired(value); - } - - public FormValidation doCheckCredential(@QueryParameter String value) { - return FormValidation.validateRequired(value); - } - - public FormValidation doCheckIdentity(@QueryParameter String value) { - return FormValidation.validateRequired(value); - } - - public FormValidation doCheckInstanceCap(@QueryParameter String value) { - return FormValidation.validatePositiveInteger(value); - } - - public FormValidation doCheckRetentionTime(@QueryParameter String value) { - try { - if (Integer.parseInt(value) == -1) - return FormValidation.ok(); - } catch (NumberFormatException e) { - } - return FormValidation.validateNonNegativeInteger(value); - } - - public FormValidation doCheckScriptTimeout(@QueryParameter String value) { - return FormValidation.validatePositiveInteger(value); - } - - public FormValidation doCheckStartTimeout(@QueryParameter String value) { - return FormValidation.validatePositiveInteger(value); - } - - public FormValidation doCheckEndPointUrl(@QueryParameter String value) { - if (!value.isEmpty() && !value.startsWith("http")) { - return FormValidation.error("The endpoint must be an URL"); - } - return FormValidation.ok(); - } - } + if ((getRunningNodesCount() + r.size()) >= instanceCap) { + LOGGER.info("Instance cap reached while adding capacity for label " + ((label != null) ? label.toString() : "null")); + break; // maxed out + } + + r.add(new PlannedNode(t.name, Computer.threadPoolForRemoting.submit(new Callable() { + public Node call() throws Exception { + // TODO: record the output somewhere + JCloudsSlave s = t.provisionSlave(new StreamTaskListener(System.out)); + Hudson.getInstance().addNode(s); + // Cloud instances may have a long init script. If + // we declare + // the provisioning complete by returning without + // the connect + // operation, NodeProvisioner may decide that it + // still wants + // one more instance, because it sees that (1) all + // the slaves + // are offline (because it's still being launched) + // and + // (2) there's no capacity provisioned yet. + // + // deferring the completion of provisioning until + // the launch + // goes successful prevents this problem. + s.toComputer().connect(false).get(); + return s; + } + }), Util.tryParseNumber(t.numExecutors, 1).intValue())); + excessWorkload -= t.getNumExecutors(); + } + return r; + } + + @Override + public boolean canProvision(final Label label) { + return getTemplate(label) != null; + } + + public JCloudsSlaveTemplate getTemplate(String name) { + for (JCloudsSlaveTemplate t : templates) + if (t.name.equals(name)) + return t; + return null; + } + + /** + * Gets {@link jenkins.plugins.jclouds.compute.JCloudsSlaveTemplate} that has the matching {@link Label}. + */ + public JCloudsSlaveTemplate getTemplate(Label label) { + for (JCloudsSlaveTemplate t : templates) + if (label == null || label.matches(t.getLabelSet())) + return t; + return null; + } + + /** + * Provisions a new node manually (by clicking a button in the computer list) + * + * @param req {@link StaplerRequest} + * @param rsp {@link StaplerResponse} + * @param name Name of the template to provision + * @throws ServletException + * @throws IOException + * @throws Descriptor.FormException + */ + public void doProvision(StaplerRequest req, StaplerResponse rsp, @QueryParameter String name) throws ServletException, IOException, + Descriptor.FormException { + checkPermission(PROVISION); + if (name == null) { + sendError("The slave template name query parameter is missing", req, rsp); + return; + } + JCloudsSlaveTemplate t = getTemplate(name); + if (t == null) { + sendError("No such slave template with name : " + name, req, rsp); + return; + } + + if (getRunningNodesCount() < instanceCap) { + StringWriter sw = new StringWriter(); + StreamTaskListener listener = new StreamTaskListener(sw); + JCloudsSlave node = t.provisionSlave(listener); + Hudson.getInstance().addNode(node); + rsp.sendRedirect2(req.getContextPath() + "/computer/" + node.getNodeName()); + } else { + sendError("Instance cap for this cloud is now reached for cloud profile: " + profile + " for template type " + name, req, rsp); + } + } + + /** + * Determine how many nodes are currently running for this cloud. + */ + public int getRunningNodesCount() { + int nodeCount = 0; + + for (ComputeMetadata cm : getCompute().listNodes()) { + if (NodeMetadata.class.isInstance(cm)) { + String nodeGroup = ((NodeMetadata) cm).getGroup(); + + if (getTemplate(nodeGroup) != null && !((NodeMetadata) cm).getStatus().equals(NodeMetadata.Status.SUSPENDED) + && !((NodeMetadata) cm).getStatus().equals(NodeMetadata.Status.TERMINATED)) { + nodeCount++; + } + } + } + return nodeCount; + } + + @Extension + public static class DescriptorImpl extends Descriptor { + + /** + * Human readable name of this kind of configurable object. + */ + @Override + public String getDisplayName() { + return "Cloud (JClouds)"; + } + + public FormValidation doTestConnection(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, + @QueryParameter String privateKey, @QueryParameter String endPointUrl, @QueryParameter String zones) throws IOException { + if (identity == null) + return FormValidation.error("Invalid (AccessId)."); + if (credential == null) + return FormValidation.error("Invalid credential (secret key)."); + if (privateKey == null) + return FormValidation.error("Private key is not specified. Click 'Generate Key' to generate one."); + + // Remove empty text/whitespace from the fields. + providerName = Util.fixEmptyAndTrim(providerName); + identity = Util.fixEmptyAndTrim(identity); + credential = Secret.fromString(credential).getPlainText(); + endPointUrl = Util.fixEmptyAndTrim(endPointUrl); + zones = Util.fixEmptyAndTrim(zones); + + FormValidation result = FormValidation.ok("Connection succeeded!"); + ComputeServiceContext ctx = null; + try { + Properties overrides = new Properties(); + if (!Strings.isNullOrEmpty(endPointUrl)) { + overrides.setProperty(Constants.PROPERTY_ENDPOINT, endPointUrl); + } + + ctx = ctx(providerName, identity, credential, overrides, zones); + + ctx.getComputeService().listNodes(); + } catch (Exception ex) { + result = FormValidation.error("Cannot connect to specified cloud, please check the identity and credentials: " + ex.getMessage()); + } finally { + Closeables.close(ctx, true); + } + return result; + } + + public FormValidation doGenerateKeyPair(StaplerResponse rsp, String identity, String credential) throws IOException, ServletException { + Map keyPair = SshKeys.generate(); + rsp.addHeader("script", "findPreviousFormItem(button,'privateKey').value='" + keyPair.get("private").replace("\n", "\\n") + "';" + + "findPreviousFormItem(button,'publicKey').value='" + keyPair.get("public").replace("\n", "\\n") + "';"); + return FormValidation.ok("Successfully generated private Key!"); + } + + public FormValidation doCheckPrivateKey(@QueryParameter String value) throws IOException, ServletException { + boolean hasStart = false, hasEnd = false; + BufferedReader br = new BufferedReader(new StringReader(value)); + String line; + while ((line = br.readLine()) != null) { + if (line.equals("-----BEGIN RSA PRIVATE KEY-----")) + hasStart = true; + if (line.equals("-----END RSA PRIVATE KEY-----")) + hasEnd = true; + } + if (!hasStart) + return FormValidation.error("Please make sure that the private key starts with '-----BEGIN RSA PRIVATE KEY-----'"); + if (!hasEnd) + return FormValidation.error("The private key is missing the trailing 'END RSA PRIVATE KEY' marker. Copy&paste error?"); + if (SshKeys.fingerprintPrivateKey(value) == null) + return FormValidation.error("Invalid private key, please check again or click on 'Generate Key' to generate a new key"); + return FormValidation.ok(); + } + + public ListBoxModel doFillProviderNameItems() { + ListBoxModel m = new ListBoxModel(); + + // correct the classloader so that extensions can be found + Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); + // TODO: apis need endpoints, providers don't; do something smarter + // with this stuff :) + Builder builder = ImmutableSet.builder(); + builder.addAll(Iterables.transform(Apis.viewableAs(ComputeServiceContext.class), Apis.idFunction())); + builder.addAll(Iterables.transform(Providers.viewableAs(ComputeServiceContext.class), Providers.idFunction())); + Iterable supportedProviders = ImmutableSortedSet.copyOf(builder.build()); + + for (String supportedProvider : supportedProviders) { + m.add(supportedProvider, supportedProvider); + } + return m; + } + + public AutoCompletionCandidates doAutoCompleteProviderName(@QueryParameter final String value) { + // correct the classloader so that extensions can be found + Thread.currentThread().setContextClassLoader(Apis.class.getClassLoader()); + // TODO: apis need endpoints, providers don't; do something smarter + // with this stuff :) + Builder builder = ImmutableSet.builder(); + builder.addAll(Iterables.transform(Apis.viewableAs(ComputeServiceContext.class), Apis.idFunction())); + builder.addAll(Iterables.transform(Providers.viewableAs(ComputeServiceContext.class), Providers.idFunction())); + Iterable supportedProviders = builder.build(); + + Iterable matchedProviders = Iterables.filter(supportedProviders, new Predicate() { + public boolean apply(@Nullable String input) { + return input != null && input.startsWith(value.toLowerCase()); + } + }); + + AutoCompletionCandidates candidates = new AutoCompletionCandidates(); + for (String matchedProvider : matchedProviders) { + candidates.add(matchedProvider); + } + return candidates; + } + + public FormValidation doCheckProfile(@QueryParameter String value) { + return FormValidation.validateRequired(value); + } + + public FormValidation doCheckProviderName(@QueryParameter String value) { + return FormValidation.validateRequired(value); + } + + public FormValidation doCheckPublicKey(@QueryParameter String value) { + return FormValidation.validateRequired(value); + } + + public FormValidation doCheckCredential(@QueryParameter String value) { + return FormValidation.validateRequired(value); + } + + public FormValidation doCheckIdentity(@QueryParameter String value) { + return FormValidation.validateRequired(value); + } + + public FormValidation doCheckInstanceCap(@QueryParameter String value) { + return FormValidation.validatePositiveInteger(value); + } + + public FormValidation doCheckRetentionTime(@QueryParameter String value) { + try { + if (Integer.parseInt(value) == -1) + return FormValidation.ok(); + } catch (NumberFormatException e) { + } + return FormValidation.validateNonNegativeInteger(value); + } + + public FormValidation doCheckScriptTimeout(@QueryParameter String value) { + return FormValidation.validatePositiveInteger(value); + } + + public FormValidation doCheckStartTimeout(@QueryParameter String value) { + return FormValidation.validatePositiveInteger(value); + } + + public FormValidation doCheckEndPointUrl(@QueryParameter String value) { + if (!value.isEmpty() && !value.startsWith("http")) { + return FormValidation.error("The endpoint must be an URL"); + } + return FormValidation.ok(); + } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsComputer.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsComputer.java index 93395b8e..59e771e8 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsComputer.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsComputer.java @@ -13,56 +13,56 @@ /** * JClouds version of Jenkins {@link SlaveComputer} - responsible for terminating an instance. - * + * * @author Vijay Kiran */ public class JCloudsComputer extends AbstractCloudComputer { - private static final Logger LOGGER = Logger.getLogger(JCloudsComputer.class.getName()); + private static final Logger LOGGER = Logger.getLogger(JCloudsComputer.class.getName()); - public JCloudsComputer(JCloudsSlave slave) { - super(slave); - } + public JCloudsComputer(JCloudsSlave slave) { + super(slave); + } - public String getInstanceId() { - return getName(); - } + public String getInstanceId() { + return getName(); + } - @Override - public JCloudsSlave getNode() { - return super.getNode(); - } + @Override + public JCloudsSlave getNode() { + return super.getNode(); + } - public int getRetentionTime() { - return getNode().getRetentionTime(); - } + public int getRetentionTime() { + return getNode().getRetentionTime(); + } - public String getCloudName() { - return getNode().getCloudName(); - } + public String getCloudName() { + return getNode().getCloudName(); + } - /** - * Really deletes the slave, by terminating the instance. - */ - @Override - public HttpResponse doDoDelete() throws IOException { - setTemporarilyOffline(true, OfflineCause.create(Messages._DeletedCause())); - getNode().setPendingDelete(true); - return new HttpRedirect(".."); - } + /** + * Really deletes the slave, by terminating the instance. + */ + @Override + public HttpResponse doDoDelete() throws IOException { + setTemporarilyOffline(true, OfflineCause.create(Messages._DeletedCause())); + getNode().setPendingDelete(true); + return new HttpRedirect(".."); + } - /** - * Delete the slave, terminate the instance. Can be called either by doDoDelete() or from JCloudsRetentionStrategy. - * - * @throws InterruptedException - */ - public void deleteSlave() throws IOException, InterruptedException { - LOGGER.info("Terminating " + getName() + " slave"); - JCloudsSlave slave = getNode(); - if (slave.getChannel() != null) { - slave.getChannel().close(); - } - slave.terminate(); - Hudson.getInstance().removeNode(slave); - } + /** + * Delete the slave, terminate the instance. Can be called either by doDoDelete() or from JCloudsRetentionStrategy. + * + * @throws InterruptedException + */ + public void deleteSlave() throws IOException, InterruptedException { + LOGGER.info("Terminating " + getName() + " slave"); + JCloudsSlave slave = getNode(); + if (slave.getChannel() != null) { + slave.getChannel().close(); + } + slave.terminate(); + Hudson.getInstance().removeNode(slave); + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsLauncher.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsLauncher.java index 2429d715..05d00785 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsLauncher.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsLauncher.java @@ -21,187 +21,184 @@ /** * The launcher that launches the jenkins slave.jar on the Slave. Uses the SSHKeyPair configured in the cloud profile settings, and logs in to the server via * SSH, and starts the slave.jar. - * + * * @author Vijay Kiran */ public class JCloudsLauncher extends ComputerLauncher { - private final int FAILED = -1; - private final int SAMEUSER = 0; - - /** - * Launch the Jenkins Slave on the SlaveComputer. - * - * @param computer - * @param listener - * @throws IOException - * @throws InterruptedException - */ - @Override - public void launch(SlaveComputer computer, TaskListener listener) throws IOException, InterruptedException { - - PrintStream logger = listener.getLogger(); - - final Connection bootstrapConn; - final Connection conn; - Connection cleanupConn = null; // java's code path analysis for final doesn't work that well. - boolean successful = false; - final JCloudsSlave slave = (JCloudsSlave) computer.getNode(); - final LoginCredentials credentials = slave.getCredentials(); - final NodeMetadata nodeMetadata = slave.getNodeMetaData(); - - try { - bootstrapConn = connectToSsh(nodeMetadata, logger); - int bootstrapResult = bootstrap(bootstrapConn, nodeMetadata, credentials, logger); - if (bootstrapResult == FAILED) - return; // bootstrap closed for us. - else if (bootstrapResult == SAMEUSER) - cleanupConn = bootstrapConn; // take over the connection - else { - // connect fresh as ROOT - cleanupConn = connectToSsh(nodeMetadata, logger); - if (!authenticate(cleanupConn, credentials)) { - logger.println("Authentication failed"); - return; // failed to connect as root. - } - } - conn = cleanupConn; - - SCPClient scp = conn.createSCPClient(); - logger.println("Copying slave.jar"); - scp.put(Hudson.getInstance().getJnlpJars("slave.jar").readFully(), "slave.jar", "/tmp"); - - String launchString = "cd /tmp && java " + slave.getJvmOptions() + " -jar slave.jar"; - logger.println("Launching slave agent: " + launchString); - final Session sess = conn.openSession(); - sess.execCommand(launchString); - computer.setChannel(sess.getStdout(), sess.getStdin(), logger, new Channel.Listener() { - @Override - public void onClosed(Channel channel, IOException cause) { - sess.close(); - conn.close(); - } - }); - successful = true; - } finally { - if (cleanupConn != null && !successful) - cleanupConn.close(); - } - } - - /** - * Authenticate with credentials - */ - private boolean authenticate(Connection connection, LoginCredentials credentials) throws IOException { - if (credentials.getOptionalPrivateKey().isPresent()) { - return connection.authenticateWithPublicKey(credentials.getUser(), credentials.getPrivateKey().toCharArray(), ""); - } else { - return connection.authenticateWithPassword(credentials.getUser(), credentials.getPassword()); - } - } - - /** - * Authenticates using the bootstrapConn, tries to 20 times before giving up. - * - * @param bootstrapConn - * @param nodeMetadata - * - JClouds compute instance {@link NodeMetadata} for IP address and credentials. - * @param logger - * @return - * @throws IOException - * @throws InterruptedException - */ - private int bootstrap(Connection bootstrapConn, NodeMetadata nodeMetadata, LoginCredentials credentials, PrintStream logger) throws IOException, - InterruptedException { - boolean closeBootstrap = true; - try { - int tries = 20; - boolean isAuthenticated = false; - while (tries-- > 0) { - logger.println("Authenticating as " + credentials.getUser()); - - isAuthenticated = authenticate(bootstrapConn, credentials); - - if (isAuthenticated) { - break; - } - logger.println("Authentication failed. Trying again..."); - Thread.sleep(10000); - } - if (!isAuthenticated) { - logger.println("Authentication failed"); - return FAILED; - } - closeBootstrap = false; - return SAMEUSER; - } catch (InterruptedException e) { - e.printStackTrace(logger); - throw e; - } catch (IOException e) { - e.printStackTrace(logger); - throw e; - } catch (Exception e) { - e.printStackTrace(logger); - throw new RuntimeException(e); - } finally { - if (closeBootstrap) - bootstrapConn.close(); - } - } - - /** - * Get the potential addresses to connect to, opting for public first and then private. - */ - public static String[] getConnectionAddresses(NodeMetadata nodeMetadata, PrintStream logger) { - if (nodeMetadata.getPublicAddresses().size() > 0) { - return nodeMetadata.getPublicAddresses().toArray(new String[nodeMetadata.getPublicAddresses().size()]); - } else { - logger.println("No public addresses found, so using private address."); - return nodeMetadata.getPrivateAddresses().toArray(new String[nodeMetadata.getPrivateAddresses().size()]); - } - } - - /** - * Connect to SSH, and return the connection. - * - * @param nodeMetadata - * - JClouds compute instance {@link NodeMetadata}, for credentials and the public IP. - * @param logger - * - the logger where the log messages need to be sent. - * @return - Connection - keeps trying forever, until the host closes the connection or we (the thread) die trying. - * @throws InterruptedException - */ - private Connection connectToSsh(NodeMetadata nodeMetadata, PrintStream logger) throws InterruptedException { - while (true) { - try { - - final String[] addresses = getConnectionAddresses(nodeMetadata, logger); - String host = addresses[0]; - if ("0.0.0.0".equals(host)) { - logger.println("Invalid host 0.0.0.0, your host is most likely waiting for an ip address."); - throw new IOException("goto sleep"); - } - - logger.println("Connecting to " + host + " on port " + 22 + ". "); - Connection conn = new Connection(host, 22); - conn.connect(new ServerHostKeyVerifier() { - @Override - public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) throws Exception { - return true; - } - }); - logger.println("Connected via SSH."); - return conn; // successfully connected - } catch (IOException e) { - // keep retrying until SSH comes up - logger.println("Waiting for SSH to come up. Sleeping 5."); - Thread.sleep(5000); - } - } - } - - @Override - public Descriptor getDescriptor() { - throw new UnsupportedOperationException(); - } + private final int FAILED = -1; + private final int SAMEUSER = 0; + + /** + * Launch the Jenkins Slave on the SlaveComputer. + * + * @param computer + * @param listener + * @throws IOException + * @throws InterruptedException + */ + @Override + public void launch(SlaveComputer computer, TaskListener listener) throws IOException, InterruptedException { + + PrintStream logger = listener.getLogger(); + + final Connection bootstrapConn; + final Connection conn; + Connection cleanupConn = null; // java's code path analysis for final doesn't work that well. + boolean successful = false; + final JCloudsSlave slave = (JCloudsSlave) computer.getNode(); + final LoginCredentials credentials = slave.getCredentials(); + final NodeMetadata nodeMetadata = slave.getNodeMetaData(); + + try { + bootstrapConn = connectToSsh(nodeMetadata, logger); + int bootstrapResult = bootstrap(bootstrapConn, nodeMetadata, credentials, logger); + if (bootstrapResult == FAILED) + return; // bootstrap closed for us. + else if (bootstrapResult == SAMEUSER) + cleanupConn = bootstrapConn; // take over the connection + else { + // connect fresh as ROOT + cleanupConn = connectToSsh(nodeMetadata, logger); + if (!authenticate(cleanupConn, credentials)) { + logger.println("Authentication failed"); + return; // failed to connect as root. + } + } + conn = cleanupConn; + + SCPClient scp = conn.createSCPClient(); + logger.println("Copying slave.jar"); + scp.put(Hudson.getInstance().getJnlpJars("slave.jar").readFully(), "slave.jar", "/tmp"); + + String launchString = "cd /tmp && java " + slave.getJvmOptions() + " -jar slave.jar"; + logger.println("Launching slave agent: " + launchString); + final Session sess = conn.openSession(); + sess.execCommand(launchString); + computer.setChannel(sess.getStdout(), sess.getStdin(), logger, new Channel.Listener() { + @Override + public void onClosed(Channel channel, IOException cause) { + sess.close(); + conn.close(); + } + }); + successful = true; + } finally { + if (cleanupConn != null && !successful) + cleanupConn.close(); + } + } + + /** + * Authenticate with credentials + */ + private boolean authenticate(Connection connection, LoginCredentials credentials) throws IOException { + if (credentials.getOptionalPrivateKey().isPresent()) { + return connection.authenticateWithPublicKey(credentials.getUser(), credentials.getPrivateKey().toCharArray(), ""); + } else { + return connection.authenticateWithPassword(credentials.getUser(), credentials.getPassword()); + } + } + + /** + * Authenticates using the bootstrapConn, tries to 20 times before giving up. + * + * @param bootstrapConn + * @param nodeMetadata - JClouds compute instance {@link NodeMetadata} for IP address and credentials. + * @param logger + * @return + * @throws IOException + * @throws InterruptedException + */ + private int bootstrap(Connection bootstrapConn, NodeMetadata nodeMetadata, LoginCredentials credentials, PrintStream logger) throws IOException, + InterruptedException { + boolean closeBootstrap = true; + try { + int tries = 20; + boolean isAuthenticated = false; + while (tries-- > 0) { + logger.println("Authenticating as " + credentials.getUser()); + + isAuthenticated = authenticate(bootstrapConn, credentials); + + if (isAuthenticated) { + break; + } + logger.println("Authentication failed. Trying again..."); + Thread.sleep(10000); + } + if (!isAuthenticated) { + logger.println("Authentication failed"); + return FAILED; + } + closeBootstrap = false; + return SAMEUSER; + } catch (InterruptedException e) { + e.printStackTrace(logger); + throw e; + } catch (IOException e) { + e.printStackTrace(logger); + throw e; + } catch (Exception e) { + e.printStackTrace(logger); + throw new RuntimeException(e); + } finally { + if (closeBootstrap) + bootstrapConn.close(); + } + } + + /** + * Get the potential addresses to connect to, opting for public first and then private. + */ + public static String[] getConnectionAddresses(NodeMetadata nodeMetadata, PrintStream logger) { + if (nodeMetadata.getPublicAddresses().size() > 0) { + return nodeMetadata.getPublicAddresses().toArray(new String[nodeMetadata.getPublicAddresses().size()]); + } else { + logger.println("No public addresses found, so using private address."); + return nodeMetadata.getPrivateAddresses().toArray(new String[nodeMetadata.getPrivateAddresses().size()]); + } + } + + /** + * Connect to SSH, and return the connection. + * + * @param nodeMetadata - JClouds compute instance {@link NodeMetadata}, for credentials and the public IP. + * @param logger - the logger where the log messages need to be sent. + * @return - Connection - keeps trying forever, until the host closes the connection or we (the thread) die trying. + * @throws InterruptedException + */ + private Connection connectToSsh(NodeMetadata nodeMetadata, PrintStream logger) throws InterruptedException { + while (true) { + try { + + final String[] addresses = getConnectionAddresses(nodeMetadata, logger); + String host = addresses[0]; + if ("0.0.0.0".equals(host)) { + logger.println("Invalid host 0.0.0.0, your host is most likely waiting for an ip address."); + throw new IOException("goto sleep"); + } + + logger.println("Connecting to " + host + " on port " + 22 + ". "); + Connection conn = new Connection(host, 22); + conn.connect(new ServerHostKeyVerifier() { + @Override + public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) throws Exception { + return true; + } + }); + logger.println("Connected via SSH."); + return conn; // successfully connected + } catch (IOException e) { + // keep retrying until SSH comes up + logger.println("Waiting for SSH to come up. Sleeping 5."); + Thread.sleep(5000); + } + } + } + + @Override + public Descriptor getDescriptor() { + throw new UnsupportedOperationException(); + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsOneOffSlave.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsOneOffSlave.java index 2b2f854f..c5bbd21d 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsOneOffSlave.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsOneOffSlave.java @@ -15,48 +15,48 @@ import org.kohsuke.stapler.DataBoundConstructor; public class JCloudsOneOffSlave extends BuildWrapper { - private static final Logger LOGGER = Logger.getLogger(JCloudsOneOffSlave.class.getName()); - - @DataBoundConstructor - public JCloudsOneOffSlave() { - } - - // - // convert Jenkins staticy stuff into pojos; performing as little critical stuff here as - // possible, as this method is very hard to test due to static usage, etc. - // - @Override - @SuppressWarnings("rawtypes") - public Environment setUp(AbstractBuild build, Launcher launcher, final BuildListener listener) { - if (JCloudsComputer.class.isInstance(build.getExecutor().getOwner())) { - final JCloudsComputer c = (JCloudsComputer) build.getExecutor().getOwner(); - return new Environment() { - @Override - public boolean tearDown(AbstractBuild build, final BuildListener listener) throws IOException, InterruptedException { - LOGGER.warning("Single-use slave " + c.getName() + " getting torn down."); - c.setTemporarilyOffline(true, OfflineCause.create(Messages._OneOffCause())); - return true; - } - }; - } else { - return new Environment() { - }; - } - - } - - @Extension - public static final class DescriptorImpl extends BuildWrapperDescriptor { - @Override - public String getDisplayName() { - return "JClouds Single-Use Slave"; - } - - @Override - @SuppressWarnings("rawtypes") - public boolean isApplicable(AbstractProject item) { - return true; - } - - } + private static final Logger LOGGER = Logger.getLogger(JCloudsOneOffSlave.class.getName()); + + @DataBoundConstructor + public JCloudsOneOffSlave() { + } + + // + // convert Jenkins staticy stuff into pojos; performing as little critical stuff here as + // possible, as this method is very hard to test due to static usage, etc. + // + @Override + @SuppressWarnings("rawtypes") + public Environment setUp(AbstractBuild build, Launcher launcher, final BuildListener listener) { + if (JCloudsComputer.class.isInstance(build.getExecutor().getOwner())) { + final JCloudsComputer c = (JCloudsComputer) build.getExecutor().getOwner(); + return new Environment() { + @Override + public boolean tearDown(AbstractBuild build, final BuildListener listener) throws IOException, InterruptedException { + LOGGER.warning("Single-use slave " + c.getName() + " getting torn down."); + c.setTemporarilyOffline(true, OfflineCause.create(Messages._OneOffCause())); + return true; + } + }; + } else { + return new Environment() { + }; + } + + } + + @Extension + public static final class DescriptorImpl extends BuildWrapperDescriptor { + @Override + public String getDisplayName() { + return "JClouds Single-Use Slave"; + } + + @Override + @SuppressWarnings("rawtypes") + public boolean isApplicable(AbstractProject item) { + return true; + } + + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsRetentionStrategy.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsRetentionStrategy.java index 45c6300d..a6ab8d20 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsRetentionStrategy.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsRetentionStrategy.java @@ -14,65 +14,65 @@ * @author Vijay Kiran */ public class JCloudsRetentionStrategy extends RetentionStrategy { - private transient ReentrantLock checkLock; + private transient ReentrantLock checkLock; - @DataBoundConstructor - public JCloudsRetentionStrategy() { - readResolve(); - } + @DataBoundConstructor + public JCloudsRetentionStrategy() { + readResolve(); + } - @Override - public long check(JCloudsComputer c) { - if (!checkLock.tryLock()) { - return 1; - } else { - try { - if (c.isIdle() && !c.getNode().isPendingDelete() && !disabled) { - // Get the retention time, in minutes, from the JCloudsCloud this JCloudsComputer belongs to. - final int retentionTime = c.getRetentionTime(); - // check executor to ensure we are terminating online slaves - if (retentionTime > -1 && c.countExecutors() > 0) { - final long idleMilliseconds = System.currentTimeMillis() - c.getIdleStartMilliseconds(); - if (idleMilliseconds > TimeUnit2.MINUTES.toMillis(retentionTime)) { - LOGGER.info("Setting " + c.getName() + " to be deleted."); - if (!c.isOffline()) { - c.setTemporarilyOffline(true, OfflineCause.create(Messages._DeletedCause())); - } - c.getNode().setPendingDelete(true); - } - } - } - } finally { - checkLock.unlock(); - } - } - return 1; - } + @Override + public long check(JCloudsComputer c) { + if (!checkLock.tryLock()) { + return 1; + } else { + try { + if (c.isIdle() && !c.getNode().isPendingDelete() && !disabled) { + // Get the retention time, in minutes, from the JCloudsCloud this JCloudsComputer belongs to. + final int retentionTime = c.getRetentionTime(); + // check executor to ensure we are terminating online slaves + if (retentionTime > -1 && c.countExecutors() > 0) { + final long idleMilliseconds = System.currentTimeMillis() - c.getIdleStartMilliseconds(); + if (idleMilliseconds > TimeUnit2.MINUTES.toMillis(retentionTime)) { + LOGGER.info("Setting " + c.getName() + " to be deleted."); + if (!c.isOffline()) { + c.setTemporarilyOffline(true, OfflineCause.create(Messages._DeletedCause())); + } + c.getNode().setPendingDelete(true); + } + } + } + } finally { + checkLock.unlock(); + } + } + return 1; + } - /** - * Try to connect to it ASAP. - */ - @Override - public void start(JCloudsComputer c) { - c.connect(false); - } + /** + * Try to connect to it ASAP. + */ + @Override + public void start(JCloudsComputer c) { + c.connect(false); + } - // no registration since this retention strategy is used only for cloud nodes that we provision automatically. - // @Extension - public static class DescriptorImpl extends Descriptor> { - @Override - public String getDisplayName() { - return "JClouds"; - } - } + // no registration since this retention strategy is used only for cloud nodes that we provision automatically. + // @Extension + public static class DescriptorImpl extends Descriptor> { + @Override + public String getDisplayName() { + return "JClouds"; + } + } - protected Object readResolve() { - checkLock = new ReentrantLock(false); - return this; - } + protected Object readResolve() { + checkLock = new ReentrantLock(false); + return this; + } - private static final Logger LOGGER = Logger.getLogger(JCloudsRetentionStrategy.class.getName()); + private static final Logger LOGGER = Logger.getLogger(JCloudsRetentionStrategy.class.getName()); - public static boolean disabled = Boolean.getBoolean(JCloudsRetentionStrategy.class.getName() + ".disabled"); + public static boolean disabled = Boolean.getBoolean(JCloudsRetentionStrategy.class.getName() + ".disabled"); } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlave.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlave.java index 4b1b0537..da1d1293 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlave.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlave.java @@ -21,182 +21,173 @@ /** * Jenkins Slave node - managed by JClouds. - * + * * @author Vijay Kiran */ public class JCloudsSlave extends AbstractCloudSlave { - private static final Logger LOGGER = Logger.getLogger(JCloudsSlave.class.getName()); - private transient NodeMetadata nodeMetaData; - public final boolean stopOnTerminate; - private final String cloudName; - private String nodeId; - private boolean pendingDelete; - private final int overrideRetentionTime; - private final String user; - private final String password; - private final String privateKey; - private final boolean authSudo; - private final String jvmOptions; - - @DataBoundConstructor - @SuppressWarnings("rawtypes") - public JCloudsSlave(String cloudName, String name, String nodeDescription, String remoteFS, String numExecutors, Mode mode, String labelString, - ComputerLauncher launcher, RetentionStrategy retentionStrategy, List> nodeProperties, boolean stopOnTerminate, - int overrideRetentionTime, String user, String password, String privateKey, boolean authSudo, String jvmOptions) throws Descriptor.FormException, - IOException { - super(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, nodeProperties); - this.stopOnTerminate = stopOnTerminate; - this.cloudName = cloudName; - this.overrideRetentionTime = overrideRetentionTime; - this.user = user; - this.password = password; - this.privateKey = privateKey; - this.authSudo = authSudo; - this.jvmOptions = jvmOptions; - } - - /** - * Constructs a new slave from JCloud's NodeMetadata - * - * @param cloudName - * - the name of the cloud that's provisioning this slave. - * @param fsRoot - * - where on the slave the Jenkins slave root is. - * @param metadata - * - JCloudsNodeMetadata - * @param labelString - * - Label(s) for this slave. - * @param description - * - Description of this slave. - * @param numExecutors - * - Number of executors for this slave. - * @param stopOnTerminate - * - if true, suspend the slave rather than terminating it. - * @param overrideRetentionTime - * - Retention time to use specifically for this slave, overriding the cloud default. - * @throws IOException - * @throws Descriptor.FormException - */ - public JCloudsSlave(final String cloudName, final String fsRoot, NodeMetadata metadata, final String labelString, final String description, - final String numExecutors, final boolean stopOnTerminate, final int overrideRetentionTime, String jvmOptions) throws IOException, - Descriptor.FormException { - this(cloudName, metadata.getName(), description, fsRoot, numExecutors, Mode.EXCLUSIVE, labelString, new JCloudsLauncher(), - new JCloudsRetentionStrategy(), Collections.> emptyList(), stopOnTerminate, overrideRetentionTime, metadata.getCredentials() - .getUser(), metadata.getCredentials().getPassword(), metadata.getCredentials().getPrivateKey(), metadata.getCredentials() - .shouldAuthenticateSudo(), jvmOptions); - this.nodeMetaData = metadata; - this.nodeId = nodeMetaData.getId(); - } - - /** - * Get Jclouds NodeMetadata associated with this Slave. - * - * @return {@link NodeMetadata} - */ - public NodeMetadata getNodeMetaData() { - if (this.nodeMetaData == null) { - final ComputeService compute = JCloudsCloud.getByName(cloudName).getCompute(); - this.nodeMetaData = compute.getNodeMetadata(nodeId); - } - return nodeMetaData; - } - - /** - * Get Jclouds Custom JVM Options associated with this Slave. - * - * @return jvmOptions - */ - public String getJvmOptions() { - return jvmOptions; - } - - /** - * Get Jclouds LoginCredentials associated with this Slave. - * - * If Jclouds doesn't provide credentials, use stored ones. - * - * @return {@link LoginCredentials} - */ - public LoginCredentials getCredentials() { - LoginCredentials credentials = getNodeMetaData().getCredentials(); - if (credentials == null) - credentials = LoginCredentials.builder().user(user).password(password).privateKey(privateKey).authenticateSudo(authSudo).build(); - return credentials; - } - - /** - * Get the retention time for this slave, defaulting to the parent cloud's if not set. - * - * @return overrideTime - */ - public int getRetentionTime() { - if (overrideRetentionTime > 0) { - return overrideRetentionTime; - } else { - return JCloudsCloud.getByName(cloudName).getRetentionTime(); - } - } - - /** - * Get the JClouds profile identifier for the Cloud associated with this slave. - * - * @return cloudName - */ - public String getCloudName() { - return cloudName; - } - - public boolean isPendingDelete() { - return pendingDelete; - } - - public void setPendingDelete(boolean pendingDelete) { - this.pendingDelete = pendingDelete; - } - - /** - * {@inheritDoc} - */ - @Override - public AbstractCloudComputer createComputer() { - LOGGER.info("Creating a new JClouds Slave"); - return new JCloudsComputer(this); - } - - @Extension - public static final class JCloudsSlaveDescriptor extends SlaveDescriptor { - - @Override - public String getDisplayName() { - return "JClouds Slave"; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isInstantiable() { - return false; - } - } - - /** - * Destroy the node calls {@link ComputeService#destroyNode} - * - */ - @Override - protected void _terminate(TaskListener listener) throws IOException, InterruptedException { - final ComputeService compute = JCloudsCloud.getByName(cloudName).getCompute(); - if (compute.getNodeMetadata(nodeId) != null && compute.getNodeMetadata(nodeId).getStatus().equals(NodeMetadata.Status.RUNNING)) { - if (stopOnTerminate) { - LOGGER.info("Suspending the Slave : " + getNodeName()); - compute.suspendNode(nodeId); - } else { - LOGGER.info("Terminating the Slave : " + getNodeName()); - compute.destroyNode(nodeId); - } - } else { - LOGGER.info("Slave " + getNodeName() + " is already not running."); - } - } + private static final Logger LOGGER = Logger.getLogger(JCloudsSlave.class.getName()); + private transient NodeMetadata nodeMetaData; + public final boolean stopOnTerminate; + private final String cloudName; + private String nodeId; + private boolean pendingDelete; + private final int overrideRetentionTime; + private final String user; + private final String password; + private final String privateKey; + private final boolean authSudo; + private final String jvmOptions; + + @DataBoundConstructor + @SuppressWarnings("rawtypes") + public JCloudsSlave(String cloudName, String name, String nodeDescription, String remoteFS, String numExecutors, Mode mode, String labelString, + ComputerLauncher launcher, RetentionStrategy retentionStrategy, List> nodeProperties, boolean stopOnTerminate, + int overrideRetentionTime, String user, String password, String privateKey, boolean authSudo, String jvmOptions) throws Descriptor.FormException, + IOException { + super(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, nodeProperties); + this.stopOnTerminate = stopOnTerminate; + this.cloudName = cloudName; + this.overrideRetentionTime = overrideRetentionTime; + this.user = user; + this.password = password; + this.privateKey = privateKey; + this.authSudo = authSudo; + this.jvmOptions = jvmOptions; + } + + /** + * Constructs a new slave from JCloud's NodeMetadata + * + * @param cloudName - the name of the cloud that's provisioning this slave. + * @param fsRoot - where on the slave the Jenkins slave root is. + * @param metadata - JCloudsNodeMetadata + * @param labelString - Label(s) for this slave. + * @param description - Description of this slave. + * @param numExecutors - Number of executors for this slave. + * @param stopOnTerminate - if true, suspend the slave rather than terminating it. + * @param overrideRetentionTime - Retention time to use specifically for this slave, overriding the cloud default. + * @throws IOException + * @throws Descriptor.FormException + */ + public JCloudsSlave(final String cloudName, final String fsRoot, NodeMetadata metadata, final String labelString, final String description, + final String numExecutors, final boolean stopOnTerminate, final int overrideRetentionTime, String jvmOptions) throws IOException, + Descriptor.FormException { + this(cloudName, metadata.getName(), description, fsRoot, numExecutors, Mode.EXCLUSIVE, labelString, new JCloudsLauncher(), + new JCloudsRetentionStrategy(), Collections.>emptyList(), stopOnTerminate, overrideRetentionTime, metadata.getCredentials() + .getUser(), metadata.getCredentials().getPassword(), metadata.getCredentials().getPrivateKey(), metadata.getCredentials() + .shouldAuthenticateSudo(), jvmOptions); + this.nodeMetaData = metadata; + this.nodeId = nodeMetaData.getId(); + } + + /** + * Get Jclouds NodeMetadata associated with this Slave. + * + * @return {@link NodeMetadata} + */ + public NodeMetadata getNodeMetaData() { + if (this.nodeMetaData == null) { + final ComputeService compute = JCloudsCloud.getByName(cloudName).getCompute(); + this.nodeMetaData = compute.getNodeMetadata(nodeId); + } + return nodeMetaData; + } + + /** + * Get Jclouds Custom JVM Options associated with this Slave. + * + * @return jvmOptions + */ + public String getJvmOptions() { + return jvmOptions; + } + + /** + * Get Jclouds LoginCredentials associated with this Slave. + *

+ * If Jclouds doesn't provide credentials, use stored ones. + * + * @return {@link LoginCredentials} + */ + public LoginCredentials getCredentials() { + LoginCredentials credentials = getNodeMetaData().getCredentials(); + if (credentials == null) + credentials = LoginCredentials.builder().user(user).password(password).privateKey(privateKey).authenticateSudo(authSudo).build(); + return credentials; + } + + /** + * Get the retention time for this slave, defaulting to the parent cloud's if not set. + * + * @return overrideTime + */ + public int getRetentionTime() { + if (overrideRetentionTime > 0) { + return overrideRetentionTime; + } else { + return JCloudsCloud.getByName(cloudName).getRetentionTime(); + } + } + + /** + * Get the JClouds profile identifier for the Cloud associated with this slave. + * + * @return cloudName + */ + public String getCloudName() { + return cloudName; + } + + public boolean isPendingDelete() { + return pendingDelete; + } + + public void setPendingDelete(boolean pendingDelete) { + this.pendingDelete = pendingDelete; + } + + /** + * {@inheritDoc} + */ + @Override + public AbstractCloudComputer createComputer() { + LOGGER.info("Creating a new JClouds Slave"); + return new JCloudsComputer(this); + } + + @Extension + public static final class JCloudsSlaveDescriptor extends SlaveDescriptor { + + @Override + public String getDisplayName() { + return "JClouds Slave"; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isInstantiable() { + return false; + } + } + + /** + * Destroy the node calls {@link ComputeService#destroyNode} + */ + @Override + protected void _terminate(TaskListener listener) throws IOException, InterruptedException { + final ComputeService compute = JCloudsCloud.getByName(cloudName).getCompute(); + if (compute.getNodeMetadata(nodeId) != null && compute.getNodeMetadata(nodeId).getStatus().equals(NodeMetadata.Status.RUNNING)) { + if (stopOnTerminate) { + LOGGER.info("Suspending the Slave : " + getNodeName()); + compute.suspendNode(nodeId); + } else { + LOGGER.info("Terminating the Slave : " + getNodeName()); + compute.destroyNode(nodeId); + } + } else { + LOGGER.info("Slave " + getNodeName() + " is already not running."); + } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplate.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplate.java index dbaeb8fb..cf6dc1de 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplate.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplate.java @@ -62,660 +62,660 @@ */ public class JCloudsSlaveTemplate implements Describable, Supplier { - private static final Logger LOGGER = Logger.getLogger(JCloudsSlaveTemplate.class.getName()); - private static final char SEPARATOR_CHAR = ','; - - public final String name; - public final String imageId; - public final String imageNameRegex; - public final String hardwareId; - public final double cores; - public final int ram; - public final String osFamily; - public final String labelString; - public final String description; - public final String osVersion; - public final String locationId; - public final String initScript; - public final String userData; - public final String numExecutors; - public final boolean stopOnTerminate; - public final String vmUser; - public final String vmPassword; - public final boolean preInstalledJava; - private final String jvmOptions; - public final boolean preExistingJenkinsUser; - private final String jenkinsUser; - private final String fsRoot; - public final boolean allowSudo; - public final boolean installPrivateKey; - public final int overrideRetentionTime; - public final int spoolDelayMs; - private final Object delayLockObject = new Object(); - public final boolean assignFloatingIp; - public final String keyPairName; - public final boolean assignPublicIp; - public final String networks; - public final String securityGroups; - - private transient Set labelSet; - - protected transient JCloudsCloud cloud; - - @DataBoundConstructor - public JCloudsSlaveTemplate(final String name, final String imageId, final String imageNameRegex, final String hardwareId, final double cores, - final int ram, final String osFamily, final String osVersion, final String locationId, final String labelString, final String description, - final String initScript, final String userData, final String numExecutors, final boolean stopOnTerminate, final String vmPassword, final String vmUser, - final boolean preInstalledJava, final String jvmOptions, final String jenkinsUser, final boolean preExistingJenkinsUser, final String fsRoot, - final boolean allowSudo, final boolean installPrivateKey, final int overrideRetentionTime, final int spoolDelayMs, final boolean assignFloatingIp, - final String keyPairName, final boolean assignPublicIp, final String networks, final String securityGroups) { - - this.name = Util.fixEmptyAndTrim(name); - this.imageId = Util.fixEmptyAndTrim(imageId); - this.imageNameRegex = Util.fixEmptyAndTrim(imageNameRegex); - this.hardwareId = Util.fixEmptyAndTrim(hardwareId); - this.cores = cores; - this.ram = ram; - this.osFamily = Util.fixNull(osFamily); - this.osVersion = Util.fixNull(osVersion); - this.locationId = Util.fixEmptyAndTrim(locationId); - this.labelString = Util.fixNull(labelString); - this.description = Util.fixNull(description); - this.initScript = Util.fixNull(initScript); - this.userData = Util.fixNull(userData); - this.numExecutors = Util.fixNull(numExecutors); - this.vmPassword = Util.fixEmptyAndTrim(vmPassword); - this.vmUser = Util.fixEmptyAndTrim(vmUser); - this.preInstalledJava = preInstalledJava; - this.jvmOptions = Util.fixEmptyAndTrim(jvmOptions); - this.stopOnTerminate = stopOnTerminate; - this.jenkinsUser = Util.fixEmptyAndTrim(jenkinsUser); - this.preExistingJenkinsUser = preExistingJenkinsUser; - this.fsRoot = Util.fixEmptyAndTrim(fsRoot); - this.allowSudo = allowSudo; - this.installPrivateKey = installPrivateKey; - this.overrideRetentionTime = overrideRetentionTime; - this.spoolDelayMs = spoolDelayMs; - this.assignFloatingIp = assignFloatingIp; - this.keyPairName = keyPairName; - this.assignPublicIp = assignPublicIp; - this.networks = networks; - this.securityGroups = securityGroups; - readResolve(); - } - - public JCloudsCloud getCloud() { - return cloud; - } - - /** - * Initializes data structure that we don't persist. - */ - protected Object readResolve() { - labelSet = Label.parse(labelString); - return this; - } - - public String getJenkinsUser() { - if (jenkinsUser == null || jenkinsUser.equals("")) { - return "jenkins"; - } else { - return jenkinsUser; - } - } - - public String getJvmOptions() { - if (jvmOptions == null) { - return ""; - } else { - return jvmOptions; - } - } - - public int getNumExecutors() { - return Util.tryParseNumber(numExecutors, 1).intValue(); - } - - public String getFsRoot() { - if (fsRoot == null || fsRoot.equals("")) { - return "/jenkins"; - } else { - return fsRoot; - } - } - - public Set getLabelSet() { - return labelSet; - } - - public JCloudsSlave provisionSlave(TaskListener listener) throws IOException { - NodeMetadata nodeMetadata = get(); - - try { - return new JCloudsSlave(getCloud().getDisplayName(), getFsRoot(), nodeMetadata, labelString, description, numExecutors, stopOnTerminate, - overrideRetentionTime, getJvmOptions()); - } catch (Descriptor.FormException e) { - throw new AssertionError("Invalid configuration " + e.getMessage()); - } - } - - @Override - public NodeMetadata get() { - LOGGER.info("Provisioning new jclouds node"); - ImmutableMap userMetadata = ImmutableMap.of("Name", name); - TemplateBuilder templateBuilder = getCloud().getCompute().templateBuilder(); - if (!Strings.isNullOrEmpty(imageId)) { - LOGGER.info("Setting image id to " + imageId); - templateBuilder.imageId(imageId); - } else if (!Strings.isNullOrEmpty(imageNameRegex)) { - LOGGER.info("Setting image name regex to " + imageNameRegex); - templateBuilder.imageNameMatches(imageNameRegex); - } else { - if (!Strings.isNullOrEmpty(osFamily)) { - LOGGER.info("Setting osFamily to " + osFamily); - templateBuilder.osFamily(OsFamily.fromValue(osFamily)); - } - if (!Strings.isNullOrEmpty(osVersion)) { - LOGGER.info("Setting osVersion to " + osVersion); - templateBuilder.osVersionMatches(osVersion); - } - } - if (!Strings.isNullOrEmpty((hardwareId))) { - LOGGER.info("Setting hardware Id to " + hardwareId); - templateBuilder.hardwareId(hardwareId); - } else { - LOGGER.info("Setting minRam " + ram + " and minCores " + cores); - templateBuilder.minCores(cores).minRam(ram); - } - if (!Strings.isNullOrEmpty(locationId)) { - LOGGER.info("Setting location Id to " + locationId); - templateBuilder.locationId(locationId); - } - - Template template = templateBuilder.build(); - TemplateOptions options = template.getOptions(); - - if (!Strings.isNullOrEmpty(networks)){ - LOGGER.info("Setting networks to " + networks); - options.networks(csvToArray(networks)); - } + private static final Logger LOGGER = Logger.getLogger(JCloudsSlaveTemplate.class.getName()); + private static final char SEPARATOR_CHAR = ','; + + public final String name; + public final String imageId; + public final String imageNameRegex; + public final String hardwareId; + public final double cores; + public final int ram; + public final String osFamily; + public final String labelString; + public final String description; + public final String osVersion; + public final String locationId; + public final String initScript; + public final String userData; + public final String numExecutors; + public final boolean stopOnTerminate; + public final String vmUser; + public final String vmPassword; + public final boolean preInstalledJava; + private final String jvmOptions; + public final boolean preExistingJenkinsUser; + private final String jenkinsUser; + private final String fsRoot; + public final boolean allowSudo; + public final boolean installPrivateKey; + public final int overrideRetentionTime; + public final int spoolDelayMs; + private final Object delayLockObject = new Object(); + public final boolean assignFloatingIp; + public final String keyPairName; + public final boolean assignPublicIp; + public final String networks; + public final String securityGroups; + + private transient Set labelSet; + + protected transient JCloudsCloud cloud; + + @DataBoundConstructor + public JCloudsSlaveTemplate(final String name, final String imageId, final String imageNameRegex, final String hardwareId, final double cores, + final int ram, final String osFamily, final String osVersion, final String locationId, final String labelString, final String description, + final String initScript, final String userData, final String numExecutors, final boolean stopOnTerminate, final String vmPassword, final String vmUser, + final boolean preInstalledJava, final String jvmOptions, final String jenkinsUser, final boolean preExistingJenkinsUser, final String fsRoot, + final boolean allowSudo, final boolean installPrivateKey, final int overrideRetentionTime, final int spoolDelayMs, final boolean assignFloatingIp, + final String keyPairName, final boolean assignPublicIp, final String networks, final String securityGroups) { + + this.name = Util.fixEmptyAndTrim(name); + this.imageId = Util.fixEmptyAndTrim(imageId); + this.imageNameRegex = Util.fixEmptyAndTrim(imageNameRegex); + this.hardwareId = Util.fixEmptyAndTrim(hardwareId); + this.cores = cores; + this.ram = ram; + this.osFamily = Util.fixNull(osFamily); + this.osVersion = Util.fixNull(osVersion); + this.locationId = Util.fixEmptyAndTrim(locationId); + this.labelString = Util.fixNull(labelString); + this.description = Util.fixNull(description); + this.initScript = Util.fixNull(initScript); + this.userData = Util.fixNull(userData); + this.numExecutors = Util.fixNull(numExecutors); + this.vmPassword = Util.fixEmptyAndTrim(vmPassword); + this.vmUser = Util.fixEmptyAndTrim(vmUser); + this.preInstalledJava = preInstalledJava; + this.jvmOptions = Util.fixEmptyAndTrim(jvmOptions); + this.stopOnTerminate = stopOnTerminate; + this.jenkinsUser = Util.fixEmptyAndTrim(jenkinsUser); + this.preExistingJenkinsUser = preExistingJenkinsUser; + this.fsRoot = Util.fixEmptyAndTrim(fsRoot); + this.allowSudo = allowSudo; + this.installPrivateKey = installPrivateKey; + this.overrideRetentionTime = overrideRetentionTime; + this.spoolDelayMs = spoolDelayMs; + this.assignFloatingIp = assignFloatingIp; + this.keyPairName = keyPairName; + this.assignPublicIp = assignPublicIp; + this.networks = networks; + this.securityGroups = securityGroups; + readResolve(); + } + + public JCloudsCloud getCloud() { + return cloud; + } + + /** + * Initializes data structure that we don't persist. + */ + protected Object readResolve() { + labelSet = Label.parse(labelString); + return this; + } + + public String getJenkinsUser() { + if (jenkinsUser == null || jenkinsUser.equals("")) { + return "jenkins"; + } else { + return jenkinsUser; + } + } - if (!Strings.isNullOrEmpty(securityGroups)){ - LOGGER.info("Setting security groups to " + securityGroups); - options.securityGroups(csvToArray(securityGroups)); - } + public String getJvmOptions() { + if (jvmOptions == null) { + return ""; + } else { + return jvmOptions; + } + } + + public int getNumExecutors() { + return Util.tryParseNumber(numExecutors, 1).intValue(); + } + + public String getFsRoot() { + if (fsRoot == null || fsRoot.equals("")) { + return "/jenkins"; + } else { + return fsRoot; + } + } + + public Set getLabelSet() { + return labelSet; + } + + public JCloudsSlave provisionSlave(TaskListener listener) throws IOException { + NodeMetadata nodeMetadata = get(); + + try { + return new JCloudsSlave(getCloud().getDisplayName(), getFsRoot(), nodeMetadata, labelString, description, numExecutors, stopOnTerminate, + overrideRetentionTime, getJvmOptions()); + } catch (Descriptor.FormException e) { + throw new AssertionError("Invalid configuration " + e.getMessage()); + } + } + + @Override + public NodeMetadata get() { + LOGGER.info("Provisioning new jclouds node"); + ImmutableMap userMetadata = ImmutableMap.of("Name", name); + TemplateBuilder templateBuilder = getCloud().getCompute().templateBuilder(); + if (!Strings.isNullOrEmpty(imageId)) { + LOGGER.info("Setting image id to " + imageId); + templateBuilder.imageId(imageId); + } else if (!Strings.isNullOrEmpty(imageNameRegex)) { + LOGGER.info("Setting image name regex to " + imageNameRegex); + templateBuilder.imageNameMatches(imageNameRegex); + } else { + if (!Strings.isNullOrEmpty(osFamily)) { + LOGGER.info("Setting osFamily to " + osFamily); + templateBuilder.osFamily(OsFamily.fromValue(osFamily)); + } + if (!Strings.isNullOrEmpty(osVersion)) { + LOGGER.info("Setting osVersion to " + osVersion); + templateBuilder.osVersionMatches(osVersion); + } + } + if (!Strings.isNullOrEmpty((hardwareId))) { + LOGGER.info("Setting hardware Id to " + hardwareId); + templateBuilder.hardwareId(hardwareId); + } else { + LOGGER.info("Setting minRam " + ram + " and minCores " + cores); + templateBuilder.minCores(cores).minRam(ram); + } + if (!Strings.isNullOrEmpty(locationId)) { + LOGGER.info("Setting location Id to " + locationId); + templateBuilder.locationId(locationId); + } + + Template template = templateBuilder.build(); + TemplateOptions options = template.getOptions(); - if (assignFloatingIp && options instanceof NovaTemplateOptions) { - LOGGER.info("Setting autoAssignFloatingIp to true"); - options.as(NovaTemplateOptions.class).autoAssignFloatingIp(true); - } - - if (!Strings.isNullOrEmpty((keyPairName)) && options instanceof NovaTemplateOptions) { - LOGGER.info("Setting keyPairName to " + keyPairName); - options.as(NovaTemplateOptions.class).keyPairName(keyPairName); - } - - if (options instanceof CloudStackTemplateOptions) { - /** - * This tells jclouds cloudstack module to assign a public ip, setup staticnat and configure the firewall when true. Only interesting when using - * cloudstack advanced networking. - */ - LOGGER.info("Setting setupStaticNat to " + assignPublicIp); - options.as(CloudStackTemplateOptions.class).setupStaticNat(assignPublicIp); - } - - if (!Strings.isNullOrEmpty(vmPassword)) { - LoginCredentials lc = LoginCredentials.builder().user(vmUser).password(vmPassword).build(); - options.overrideLoginCredentials(lc); - } else if (!Strings.isNullOrEmpty(getCloud().privateKey) && !Strings.isNullOrEmpty(vmUser)) { + if (!Strings.isNullOrEmpty(networks)) { + LOGGER.info("Setting networks to " + networks); + options.networks(csvToArray(networks)); + } + + if (!Strings.isNullOrEmpty(securityGroups)) { + LOGGER.info("Setting security groups to " + securityGroups); + options.securityGroups(csvToArray(securityGroups)); + } + + if (assignFloatingIp && options instanceof NovaTemplateOptions) { + LOGGER.info("Setting autoAssignFloatingIp to true"); + options.as(NovaTemplateOptions.class).autoAssignFloatingIp(true); + } + + if (!Strings.isNullOrEmpty((keyPairName)) && options instanceof NovaTemplateOptions) { + LOGGER.info("Setting keyPairName to " + keyPairName); + options.as(NovaTemplateOptions.class).keyPairName(keyPairName); + } + + if (options instanceof CloudStackTemplateOptions) { + /** + * This tells jclouds cloudstack module to assign a public ip, setup staticnat and configure the firewall when true. Only interesting when using + * cloudstack advanced networking. + */ + LOGGER.info("Setting setupStaticNat to " + assignPublicIp); + options.as(CloudStackTemplateOptions.class).setupStaticNat(assignPublicIp); + } + + if (!Strings.isNullOrEmpty(vmPassword)) { + LoginCredentials lc = LoginCredentials.builder().user(vmUser).password(vmPassword).build(); + options.overrideLoginCredentials(lc); + } else if (!Strings.isNullOrEmpty(getCloud().privateKey) && !Strings.isNullOrEmpty(vmUser)) { // Skip overriding the credentials if we don't have a VM admin user specified - there are cases where we want the private // key but we don't to use it for the admin user creds. - LoginCredentials lc = LoginCredentials.builder().user(vmUser).privateKey(getCloud().privateKey).build(); - options.overrideLoginCredentials(lc); - } - - if (spoolDelayMs > 0) { - // (JENKINS-15970) Add optional delay before spooling. Author: Adam Rofer - synchronized (delayLockObject) { - LOGGER.info("Delaying " + spoolDelayMs + " milliseconds. Current ms -> " + System.currentTimeMillis()); - try { - Thread.sleep(spoolDelayMs); - } catch (InterruptedException e) { - } - } - } - - Statement initStatement = null; - Statement bootstrap = null; - - if (this.preExistingJenkinsUser) { - if (this.initScript.length() > 0) { - initStatement = Statements.exec(this.initScript); - } - } else { - // setup the jcloudTemplate to customize the nodeMetadata with jdk, etc. also opening ports - AdminAccess adminAccess = AdminAccess.builder().adminUsername(getJenkinsUser()) - .installAdminPrivateKey(installPrivateKey) // some VCS such as Git use SSH authentication - .grantSudoToAdminUser(allowSudo) // no need - .adminPrivateKey(getCloud().privateKey) // temporary due to jclouds bug - .authorizeAdminPublicKey(true).adminPublicKey(getCloud().publicKey).adminHome(getFsRoot()).build(); - - // Jenkins needs /jenkins dir. - Statement jenkinsDirStatement = Statements.newStatementList(Statements.exec("mkdir -p " + getFsRoot()), - Statements.exec("chown " + getJenkinsUser() + " " + getFsRoot())); - - initStatement = newStatementList(adminAccess, jenkinsDirStatement, Statements.exec(this.initScript)); - } - - if (preInstalledJava) { - bootstrap = initStatement; - } else { - bootstrap = newStatementList(initStatement, InstallJDK.fromOpenJDK()); - } - - options.inboundPorts(22).userMetadata(userMetadata); - - if (bootstrap != null) { - options.runScript(bootstrap); - } - - if (userData != null) { - try { - Method userDataMethod = options.getClass().getMethod("userData", new byte[0].getClass()); - LOGGER.info("Setting userData to " + userData); - userDataMethod.invoke(options, userData.getBytes()); - } catch (Exception e) { - LOGGER.log(Level.WARNING, "userData is not supported by provider options class " + options.getClass().getName(), e); - } - } - - NodeMetadata nodeMetadata = null; - - try { - nodeMetadata = getOnlyElement(getCloud().getCompute().createNodesInGroup(name, 1, template)); - } catch (RunNodesException e) { - throw destroyBadNodesAndPropagate(e); - } - - // Check if nodeMetadata is null and throw - return nodeMetadata; - } - - private RuntimeException destroyBadNodesAndPropagate(RunNodesException e) { - for (Map.Entry nodeError : e.getNodeErrors().entrySet()) { - getCloud().getCompute().destroyNode(nodeError.getKey().getId()); - } - throw propagate(e); - } - - private static String[] csvToArray(final String csv) { - try { + LoginCredentials lc = LoginCredentials.builder().user(vmUser).privateKey(getCloud().privateKey).build(); + options.overrideLoginCredentials(lc); + } + + if (spoolDelayMs > 0) { + // (JENKINS-15970) Add optional delay before spooling. Author: Adam Rofer + synchronized (delayLockObject) { + LOGGER.info("Delaying " + spoolDelayMs + " milliseconds. Current ms -> " + System.currentTimeMillis()); + try { + Thread.sleep(spoolDelayMs); + } catch (InterruptedException e) { + } + } + } + + Statement initStatement = null; + Statement bootstrap = null; + + if (this.preExistingJenkinsUser) { + if (this.initScript.length() > 0) { + initStatement = Statements.exec(this.initScript); + } + } else { + // setup the jcloudTemplate to customize the nodeMetadata with jdk, etc. also opening ports + AdminAccess adminAccess = AdminAccess.builder().adminUsername(getJenkinsUser()) + .installAdminPrivateKey(installPrivateKey) // some VCS such as Git use SSH authentication + .grantSudoToAdminUser(allowSudo) // no need + .adminPrivateKey(getCloud().privateKey) // temporary due to jclouds bug + .authorizeAdminPublicKey(true).adminPublicKey(getCloud().publicKey).adminHome(getFsRoot()).build(); + + // Jenkins needs /jenkins dir. + Statement jenkinsDirStatement = Statements.newStatementList(Statements.exec("mkdir -p " + getFsRoot()), + Statements.exec("chown " + getJenkinsUser() + " " + getFsRoot())); + + initStatement = newStatementList(adminAccess, jenkinsDirStatement, Statements.exec(this.initScript)); + } + + if (preInstalledJava) { + bootstrap = initStatement; + } else { + bootstrap = newStatementList(initStatement, InstallJDK.fromOpenJDK()); + } + + options.inboundPorts(22).userMetadata(userMetadata); + + if (bootstrap != null) { + options.runScript(bootstrap); + } + + if (userData != null) { + try { + Method userDataMethod = options.getClass().getMethod("userData", new byte[0].getClass()); + LOGGER.info("Setting userData to " + userData); + userDataMethod.invoke(options, userData.getBytes()); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "userData is not supported by provider options class " + options.getClass().getName(), e); + } + } + + NodeMetadata nodeMetadata = null; + + try { + nodeMetadata = getOnlyElement(getCloud().getCompute().createNodesInGroup(name, 1, template)); + } catch (RunNodesException e) { + throw destroyBadNodesAndPropagate(e); + } + + // Check if nodeMetadata is null and throw + return nodeMetadata; + } + + private RuntimeException destroyBadNodesAndPropagate(RunNodesException e) { + for (Map.Entry nodeError : e.getNodeErrors().entrySet()) { + getCloud().getCompute().destroyNode(nodeError.getKey().getId()); + } + throw propagate(e); + } + + private static String[] csvToArray(final String csv) { + try { final CSVReader reader = new CSVReader(new StringReader(csv), SEPARATOR_CHAR); final String[] line = reader.readNext(); - return (line != null) ? line: new String[0]; - } catch (Exception e) { + return (line != null) ? line : new String[0]; + } catch (Exception e) { return new String[0]; - } - } - - @Override - @SuppressWarnings("unchecked") - public Descriptor getDescriptor() { - return Jenkins.getInstance().getDescriptor(getClass()); - } - - @Extension - public static final class DescriptorImpl extends Descriptor { - - @Override - public String getDisplayName() { - return null; - } - - public FormValidation doCheckName(@QueryParameter String value) { - try { - new DnsNameValidator(1, 80).validate(value); - return FormValidation.ok(); - } catch (Exception e) { - return FormValidation.error(e.getMessage()); - } - } - - public FormValidation doCheckCores(@QueryParameter String value) { - return FormValidation.validateRequired(value); - } - - public FormValidation doCheckRam(@QueryParameter String value) { - return FormValidation.validateRequired(value); - } - - public AutoCompletionCandidates doAutoCompleteOsFamily(@QueryParameter final String value) { - OsFamily[] osFamilies = OsFamily.values(); - - AutoCompletionCandidates candidates = new AutoCompletionCandidates(); - for (OsFamily osFamily : osFamilies) { - if (StringUtils.containsIgnoreCase(osFamily.toString(), value)) { - // note: string form of osFamily is lower-hyphen - candidates.add(osFamily.toString()); - } - } - return candidates; - } - - public FormValidation doCheckNumExecutors(@QueryParameter String value) { - return FormValidation.validatePositiveInteger(value); - } - - public FormValidation doValidateImageId(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, - @QueryParameter String endPointUrl, @QueryParameter String imageId, @QueryParameter String zones) { - - final FormValidation computeContextValidationResult = validateComputeContextParameters(providerName, identity, credential, endPointUrl, zones); - if (computeContextValidationResult != null) { - return computeContextValidationResult; - } - if (Strings.isNullOrEmpty(imageId)) { - return FormValidation.error("Image Id shouldn't be empty"); - } - - // Remove empty text/whitespace from the fields. - imageId = Util.fixEmptyAndTrim(imageId); - - try { - final Set images = listImages(providerName, identity, Secret.fromString(credential).getPlainText(), endPointUrl, zones); - if (images != null) { - for (final Image image : images) { - if (!image.getId().equals(imageId)) { - if (image.getId().contains(imageId)) { - return FormValidation.warning("Sorry cannot find the image id, " + "Did you mean: " + image.getId() + "?\n" + image); - } - } else { - return FormValidation.ok("Image Id is valid."); - } - } - } - } catch (Exception ex) { - return FormValidation.error("Unable to check the image id, " + "please check if the credentials you provided are correct.", ex); - } - return FormValidation.error("Invalid Image Id, please check the value and try again."); - } - - public FormValidation doValidateImageNameRegex(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, - @QueryParameter String endPointUrl, @QueryParameter String imageNameRegex, @QueryParameter String zones) { - - final FormValidation computeContextValidationResult = validateComputeContextParameters(providerName, identity, Secret.fromString(credential).getPlainText(), endPointUrl, zones); - if (computeContextValidationResult != null) { - return computeContextValidationResult; - } - if (Strings.isNullOrEmpty(imageNameRegex)) { - return FormValidation.error("Image Name Regex shouldn't be empty"); - } - - // Remove empty text/whitespace from the fields. - imageNameRegex = Util.fixEmptyAndTrim(imageNameRegex); - - try { - final Set images = listImages(providerName, identity, Secret.fromString(credential).getPlainText(), endPointUrl, zones); - if (images != null) { - for (final Image image : images) { - if (image.getName().matches(imageNameRegex)) { - return FormValidation.ok("Image Name Regex is valid."); - } - } - } - } catch (Exception ex) { - return FormValidation.error("Unable to check the image name regex, " + "please check if the credentials you provided are correct.", ex); - } - return FormValidation.error("Invalid Image Name Regex, please check the value and try again."); - } - - private FormValidation validateComputeContextParameters(@QueryParameter String providerName, @QueryParameter String identity, - @QueryParameter String credential, @QueryParameter String endPointUrl, @QueryParameter String zones) { - if (Strings.isNullOrEmpty(identity)) { - return FormValidation.error("Invalid identity (AccessId)."); - } - if (Strings.isNullOrEmpty(credential)) { - return FormValidation.error("Invalid credential (secret key)."); - } - if (Strings.isNullOrEmpty(providerName)) { - return FormValidation.error("Provider Name shouldn't be empty"); - } - - return null; - } - - private Set listImages(String providerName, String identity, String credential, String endPointUrl, String zones) { - // Remove empty text/whitespace from the fields. - providerName = Util.fixEmptyAndTrim(providerName); - identity = Util.fixEmptyAndTrim(identity); - credential = Secret.fromString(credential).getPlainText(); - endPointUrl = Util.fixEmptyAndTrim(endPointUrl); - zones = Util.fixEmptyAndTrim(zones); - ComputeService computeService = null; - - try { - computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); - return computeService.listImages(); - } finally { - if (computeService != null) { - computeService.getContext().close(); - } - } - } - - public ListBoxModel doFillHardwareIdItems(@RelativePath("..") @QueryParameter String providerName, @RelativePath("..") @QueryParameter String identity, - @RelativePath("..") @QueryParameter String credential, @RelativePath("..") @QueryParameter String endPointUrl, - @RelativePath("..") @QueryParameter String zones) { - - ListBoxModel m = new ListBoxModel(); - - if (Strings.isNullOrEmpty(identity)) { - LOGGER.warning("identity is null or empty"); - return m; - } - if (Strings.isNullOrEmpty(credential)) { - LOGGER.warning("credential is null or empty"); - return m; - } - if (Strings.isNullOrEmpty(providerName)) { - LOGGER.warning("providerName is null or empty"); - return m; - } - - // Remove empty text/whitespace from the fields. - providerName = Util.fixEmptyAndTrim(providerName); - identity = Util.fixEmptyAndTrim(identity); - credential = Secret.fromString(credential).getPlainText(); - endPointUrl = Util.fixEmptyAndTrim(endPointUrl); - - ComputeService computeService = null; - m.add("None specified", ""); - try { - // TODO: endpoint is ignored - computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); - - ArrayList hws = newArrayList(computeService.listHardwareProfiles()); - sort(hws); - - for (Hardware hardware : hws) { - m.add(String.format("%s (%s)", hardware.getId(), hardware.getName()), hardware.getId()); - } - } catch (Exception ex) { - LOGGER.log(Level.SEVERE, ex.getMessage(), ex); - } finally { - if (computeService != null) { - computeService.getContext().close(); - } - } - - return m; - } - - public FormValidation doValidateHardwareId(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, - @QueryParameter String endPointUrl, @QueryParameter String hardwareId, @QueryParameter String zones) { - - if (Strings.isNullOrEmpty(identity)) { - return FormValidation.error("Invalid identity (AccessId)."); - } - if (Strings.isNullOrEmpty(credential)) { - return FormValidation.error("Invalid credential (secret key)."); - } - if (Strings.isNullOrEmpty(providerName)) { - return FormValidation.error("Provider Name shouldn't be empty"); - } - if (Strings.isNullOrEmpty(hardwareId)) { - return FormValidation.error("Hardware Id shouldn't be empty"); - } - - // Remove empty text/whitespace from the fields. - providerName = Util.fixEmptyAndTrim(providerName); - identity = Util.fixEmptyAndTrim(identity); - credential = Secret.fromString(credential).getPlainText(); - hardwareId = Util.fixEmptyAndTrim(hardwareId); - endPointUrl = Util.fixEmptyAndTrim(endPointUrl); - zones = Util.fixEmptyAndTrim(zones); - - FormValidation result = FormValidation.error("Invalid Hardware Id, please check the value and try again."); - ComputeService computeService = null; - try { - // TODO: endpoint is ignored - computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); - Set hardwareProfiles = computeService.listHardwareProfiles(); - for (Hardware hardware : hardwareProfiles) { - if (!hardware.getId().equals(hardwareId)) { - if (hardware.getId().contains(hardwareId)) { - return FormValidation.warning("Sorry cannot find the hardware id, " + "Did you mean: " + hardware.getId() + "?\n" + hardware); - } - } else { - return FormValidation.ok("Hardware Id is valid."); - } - } - - } catch (Exception ex) { - result = FormValidation.error("Unable to check the hardware id, " + "please check if the credentials you provided are correct.", ex); - } finally { - if (computeService != null) { - computeService.getContext().close(); - } - } - return result; - } - - public ListBoxModel doFillLocationIdItems(@RelativePath("..") @QueryParameter String providerName, @RelativePath("..") @QueryParameter String identity, - @RelativePath("..") @QueryParameter String credential, @RelativePath("..") @QueryParameter String endPointUrl, - @RelativePath("..") @QueryParameter String zones) { - - ListBoxModel m = new ListBoxModel(); - - if (Strings.isNullOrEmpty(identity)) { - LOGGER.warning("identity is null or empty"); - return m; - } - if (Strings.isNullOrEmpty(credential)) { - LOGGER.warning("credential is null or empty"); + } + } + + @Override + @SuppressWarnings("unchecked") + public Descriptor getDescriptor() { + return Jenkins.getInstance().getDescriptor(getClass()); + } + + @Extension + public static final class DescriptorImpl extends Descriptor { + + @Override + public String getDisplayName() { + return null; + } + + public FormValidation doCheckName(@QueryParameter String value) { + try { + new DnsNameValidator(1, 80).validate(value); + return FormValidation.ok(); + } catch (Exception e) { + return FormValidation.error(e.getMessage()); + } + } + + public FormValidation doCheckCores(@QueryParameter String value) { + return FormValidation.validateRequired(value); + } + + public FormValidation doCheckRam(@QueryParameter String value) { + return FormValidation.validateRequired(value); + } + + public AutoCompletionCandidates doAutoCompleteOsFamily(@QueryParameter final String value) { + OsFamily[] osFamilies = OsFamily.values(); + + AutoCompletionCandidates candidates = new AutoCompletionCandidates(); + for (OsFamily osFamily : osFamilies) { + if (StringUtils.containsIgnoreCase(osFamily.toString(), value)) { + // note: string form of osFamily is lower-hyphen + candidates.add(osFamily.toString()); + } + } + return candidates; + } + + public FormValidation doCheckNumExecutors(@QueryParameter String value) { + return FormValidation.validatePositiveInteger(value); + } + + public FormValidation doValidateImageId(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, + @QueryParameter String endPointUrl, @QueryParameter String imageId, @QueryParameter String zones) { + + final FormValidation computeContextValidationResult = validateComputeContextParameters(providerName, identity, credential, endPointUrl, zones); + if (computeContextValidationResult != null) { + return computeContextValidationResult; + } + if (Strings.isNullOrEmpty(imageId)) { + return FormValidation.error("Image Id shouldn't be empty"); + } + + // Remove empty text/whitespace from the fields. + imageId = Util.fixEmptyAndTrim(imageId); + + try { + final Set images = listImages(providerName, identity, Secret.fromString(credential).getPlainText(), endPointUrl, zones); + if (images != null) { + for (final Image image : images) { + if (!image.getId().equals(imageId)) { + if (image.getId().contains(imageId)) { + return FormValidation.warning("Sorry cannot find the image id, " + "Did you mean: " + image.getId() + "?\n" + image); + } + } else { + return FormValidation.ok("Image Id is valid."); + } + } + } + } catch (Exception ex) { + return FormValidation.error("Unable to check the image id, " + "please check if the credentials you provided are correct.", ex); + } + return FormValidation.error("Invalid Image Id, please check the value and try again."); + } + + public FormValidation doValidateImageNameRegex(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, + @QueryParameter String endPointUrl, @QueryParameter String imageNameRegex, @QueryParameter String zones) { + + final FormValidation computeContextValidationResult = validateComputeContextParameters(providerName, identity, Secret.fromString(credential).getPlainText(), endPointUrl, zones); + if (computeContextValidationResult != null) { + return computeContextValidationResult; + } + if (Strings.isNullOrEmpty(imageNameRegex)) { + return FormValidation.error("Image Name Regex shouldn't be empty"); + } + + // Remove empty text/whitespace from the fields. + imageNameRegex = Util.fixEmptyAndTrim(imageNameRegex); + + try { + final Set images = listImages(providerName, identity, Secret.fromString(credential).getPlainText(), endPointUrl, zones); + if (images != null) { + for (final Image image : images) { + if (image.getName().matches(imageNameRegex)) { + return FormValidation.ok("Image Name Regex is valid."); + } + } + } + } catch (Exception ex) { + return FormValidation.error("Unable to check the image name regex, " + "please check if the credentials you provided are correct.", ex); + } + return FormValidation.error("Invalid Image Name Regex, please check the value and try again."); + } + + private FormValidation validateComputeContextParameters(@QueryParameter String providerName, @QueryParameter String identity, + @QueryParameter String credential, @QueryParameter String endPointUrl, @QueryParameter String zones) { + if (Strings.isNullOrEmpty(identity)) { + return FormValidation.error("Invalid identity (AccessId)."); + } + if (Strings.isNullOrEmpty(credential)) { + return FormValidation.error("Invalid credential (secret key)."); + } + if (Strings.isNullOrEmpty(providerName)) { + return FormValidation.error("Provider Name shouldn't be empty"); + } + + return null; + } + + private Set listImages(String providerName, String identity, String credential, String endPointUrl, String zones) { + // Remove empty text/whitespace from the fields. + providerName = Util.fixEmptyAndTrim(providerName); + identity = Util.fixEmptyAndTrim(identity); + credential = Secret.fromString(credential).getPlainText(); + endPointUrl = Util.fixEmptyAndTrim(endPointUrl); + zones = Util.fixEmptyAndTrim(zones); + ComputeService computeService = null; + + try { + computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); + return computeService.listImages(); + } finally { + if (computeService != null) { + computeService.getContext().close(); + } + } + } + + public ListBoxModel doFillHardwareIdItems(@RelativePath("..") @QueryParameter String providerName, @RelativePath("..") @QueryParameter String identity, + @RelativePath("..") @QueryParameter String credential, @RelativePath("..") @QueryParameter String endPointUrl, + @RelativePath("..") @QueryParameter String zones) { + + ListBoxModel m = new ListBoxModel(); + + if (Strings.isNullOrEmpty(identity)) { + LOGGER.warning("identity is null or empty"); + return m; + } + if (Strings.isNullOrEmpty(credential)) { + LOGGER.warning("credential is null or empty"); + return m; + } + if (Strings.isNullOrEmpty(providerName)) { + LOGGER.warning("providerName is null or empty"); + return m; + } + + // Remove empty text/whitespace from the fields. + providerName = Util.fixEmptyAndTrim(providerName); + identity = Util.fixEmptyAndTrim(identity); + credential = Secret.fromString(credential).getPlainText(); + endPointUrl = Util.fixEmptyAndTrim(endPointUrl); + + ComputeService computeService = null; + m.add("None specified", ""); + try { + // TODO: endpoint is ignored + computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); + + ArrayList hws = newArrayList(computeService.listHardwareProfiles()); + sort(hws); + + for (Hardware hardware : hws) { + m.add(String.format("%s (%s)", hardware.getId(), hardware.getName()), hardware.getId()); + } + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, ex.getMessage(), ex); + } finally { + if (computeService != null) { + computeService.getContext().close(); + } + } + return m; - } - if (Strings.isNullOrEmpty(providerName)) { - LOGGER.warning("providerName is null or empty"); + } + + public FormValidation doValidateHardwareId(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, + @QueryParameter String endPointUrl, @QueryParameter String hardwareId, @QueryParameter String zones) { + + if (Strings.isNullOrEmpty(identity)) { + return FormValidation.error("Invalid identity (AccessId)."); + } + if (Strings.isNullOrEmpty(credential)) { + return FormValidation.error("Invalid credential (secret key)."); + } + if (Strings.isNullOrEmpty(providerName)) { + return FormValidation.error("Provider Name shouldn't be empty"); + } + if (Strings.isNullOrEmpty(hardwareId)) { + return FormValidation.error("Hardware Id shouldn't be empty"); + } + + // Remove empty text/whitespace from the fields. + providerName = Util.fixEmptyAndTrim(providerName); + identity = Util.fixEmptyAndTrim(identity); + credential = Secret.fromString(credential).getPlainText(); + hardwareId = Util.fixEmptyAndTrim(hardwareId); + endPointUrl = Util.fixEmptyAndTrim(endPointUrl); + zones = Util.fixEmptyAndTrim(zones); + + FormValidation result = FormValidation.error("Invalid Hardware Id, please check the value and try again."); + ComputeService computeService = null; + try { + // TODO: endpoint is ignored + computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); + Set hardwareProfiles = computeService.listHardwareProfiles(); + for (Hardware hardware : hardwareProfiles) { + if (!hardware.getId().equals(hardwareId)) { + if (hardware.getId().contains(hardwareId)) { + return FormValidation.warning("Sorry cannot find the hardware id, " + "Did you mean: " + hardware.getId() + "?\n" + hardware); + } + } else { + return FormValidation.ok("Hardware Id is valid."); + } + } + + } catch (Exception ex) { + result = FormValidation.error("Unable to check the hardware id, " + "please check if the credentials you provided are correct.", ex); + } finally { + if (computeService != null) { + computeService.getContext().close(); + } + } + return result; + } + + public ListBoxModel doFillLocationIdItems(@RelativePath("..") @QueryParameter String providerName, @RelativePath("..") @QueryParameter String identity, + @RelativePath("..") @QueryParameter String credential, @RelativePath("..") @QueryParameter String endPointUrl, + @RelativePath("..") @QueryParameter String zones) { + + ListBoxModel m = new ListBoxModel(); + + if (Strings.isNullOrEmpty(identity)) { + LOGGER.warning("identity is null or empty"); + return m; + } + if (Strings.isNullOrEmpty(credential)) { + LOGGER.warning("credential is null or empty"); + return m; + } + if (Strings.isNullOrEmpty(providerName)) { + LOGGER.warning("providerName is null or empty"); + return m; + } + + // Remove empty text/whitespace from the fields. + providerName = Util.fixEmptyAndTrim(providerName); + identity = Util.fixEmptyAndTrim(identity); + credential = Secret.fromString(credential).getPlainText(); + endPointUrl = Util.fixEmptyAndTrim(endPointUrl); + + ComputeService computeService = null; + m.add("None specified", ""); + try { + // TODO: endpoint is ignored + computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); + + ArrayList locations = newArrayList(computeService.listAssignableLocations()); + sort(locations, new Comparator() { + @Override + public int compare(Location o1, Location o2) { + return o1.getId().compareTo(o2.getId()); + } + }); + + for (Location location : locations) { + m.add(String.format("%s (%s)", location.getId(), location.getDescription()), location.getId()); + } + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, ex.getMessage(), ex); + } finally { + if (computeService != null) { + computeService.getContext().close(); + } + } + return m; - } - - // Remove empty text/whitespace from the fields. - providerName = Util.fixEmptyAndTrim(providerName); - identity = Util.fixEmptyAndTrim(identity); - credential = Secret.fromString(credential).getPlainText(); - endPointUrl = Util.fixEmptyAndTrim(endPointUrl); - - ComputeService computeService = null; - m.add("None specified", ""); - try { - // TODO: endpoint is ignored - computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); - - ArrayList locations = newArrayList(computeService.listAssignableLocations()); - sort(locations, new Comparator() { - @Override - public int compare(Location o1, Location o2) { - return o1.getId().compareTo(o2.getId()); - } - }); - - for (Location location : locations) { - m.add(String.format("%s (%s)", location.getId(), location.getDescription()), location.getId()); - } - } catch (Exception ex) { - LOGGER.log(Level.SEVERE, ex.getMessage(), ex); - } finally { - if (computeService != null) { - computeService.getContext().close(); - } - } - - return m; - } - - public FormValidation doValidateLocationId(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, - @QueryParameter String endPointUrl, @QueryParameter String locationId, @QueryParameter String zones) { - - if (Strings.isNullOrEmpty(identity)) { - return FormValidation.error("Invalid identity (AccessId)."); - } - if (Strings.isNullOrEmpty(credential)) { - return FormValidation.error("Invalid credential (secret key)."); - } - if (Strings.isNullOrEmpty(providerName)) { - return FormValidation.error("Provider Name shouldn't be empty"); - } - - if (Strings.isNullOrEmpty(locationId)) { - return FormValidation.ok("No location configured. jclouds automatically will choose one."); - } - - // Remove empty text/whitespace from the fields. - providerName = Util.fixEmptyAndTrim(providerName); - identity = Util.fixEmptyAndTrim(identity); - credential = Util.fixEmptyAndTrim(credential); - locationId = Util.fixEmptyAndTrim(locationId); - endPointUrl = Util.fixEmptyAndTrim(endPointUrl); - zones = Util.fixEmptyAndTrim(zones); - - FormValidation result = FormValidation.error("Invalid Location Id, please check the value and try again."); - ComputeService computeService = null; - try { - // TODO: endpoint is ignored - computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); - Set locations = computeService.listAssignableLocations(); - for (Location location : locations) { - if (!location.getId().equals(locationId)) { - if (location.getId().contains(locationId)) { - return FormValidation.warning("Sorry cannot find the location id, " + "Did you mean: " + location.getId() + "?\n" + location); - } - } else { - return FormValidation.ok("Location Id is valid."); - } - } - - } catch (Exception ex) { - result = FormValidation.error("Unable to check the location id, " + "please check if the credentials you provided are correct.", ex); - } finally { - if (computeService != null) { - computeService.getContext().close(); - } - } - return result; - } - - public FormValidation doCheckOverrideRetentionTime(@QueryParameter String value) { - try { - if (Integer.parseInt(value) == -1) { - return FormValidation.ok(); - } - } catch (NumberFormatException e) { - } - return FormValidation.validateNonNegativeInteger(value); - } - - public FormValidation doCheckSpoolDelayMs(@QueryParameter String value) { - return FormValidation.validateNonNegativeInteger(value); - } - } + } + + public FormValidation doValidateLocationId(@QueryParameter String providerName, @QueryParameter String identity, @QueryParameter String credential, + @QueryParameter String endPointUrl, @QueryParameter String locationId, @QueryParameter String zones) { + + if (Strings.isNullOrEmpty(identity)) { + return FormValidation.error("Invalid identity (AccessId)."); + } + if (Strings.isNullOrEmpty(credential)) { + return FormValidation.error("Invalid credential (secret key)."); + } + if (Strings.isNullOrEmpty(providerName)) { + return FormValidation.error("Provider Name shouldn't be empty"); + } + + if (Strings.isNullOrEmpty(locationId)) { + return FormValidation.ok("No location configured. jclouds automatically will choose one."); + } + + // Remove empty text/whitespace from the fields. + providerName = Util.fixEmptyAndTrim(providerName); + identity = Util.fixEmptyAndTrim(identity); + credential = Util.fixEmptyAndTrim(credential); + locationId = Util.fixEmptyAndTrim(locationId); + endPointUrl = Util.fixEmptyAndTrim(endPointUrl); + zones = Util.fixEmptyAndTrim(zones); + + FormValidation result = FormValidation.error("Invalid Location Id, please check the value and try again."); + ComputeService computeService = null; + try { + // TODO: endpoint is ignored + computeService = JCloudsCloud.ctx(providerName, identity, credential, endPointUrl, zones).getComputeService(); + Set locations = computeService.listAssignableLocations(); + for (Location location : locations) { + if (!location.getId().equals(locationId)) { + if (location.getId().contains(locationId)) { + return FormValidation.warning("Sorry cannot find the location id, " + "Did you mean: " + location.getId() + "?\n" + location); + } + } else { + return FormValidation.ok("Location Id is valid."); + } + } + + } catch (Exception ex) { + result = FormValidation.error("Unable to check the location id, " + "please check if the credentials you provided are correct.", ex); + } finally { + if (computeService != null) { + computeService.getContext().close(); + } + } + return result; + } + + public FormValidation doCheckOverrideRetentionTime(@QueryParameter String value) { + try { + if (Integer.parseInt(value) == -1) { + return FormValidation.ok(); + } + } catch (NumberFormatException e) { + } + return FormValidation.validateNonNegativeInteger(value); + } + + public FormValidation doCheckSpoolDelayMs(@QueryParameter String value) { + return FormValidation.validateNonNegativeInteger(value); + } + } } diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/NodePlan.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/NodePlan.java index a76e8f2e..79195f6b 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/NodePlan.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/NodePlan.java @@ -5,37 +5,37 @@ import shaded.com.google.common.base.Supplier; public class NodePlan { - private final String cloudName; - private final String templateName; - private final int count; - private final boolean suspendOrTerminate; - private final Supplier nodeSupplier; - - public NodePlan(String cloud, String template, int count, boolean suspendOrTerminate, Supplier nodeSupplier) { - this.cloudName = cloud; - this.templateName = template; - this.count = count; - this.suspendOrTerminate = suspendOrTerminate; - this.nodeSupplier = nodeSupplier; - } - - public String getCloudName() { - return cloudName; - } - - public String getTemplateName() { - return templateName; - } - - public int getCount() { - return count; - } - - public boolean isSuspendOrTerminate() { - return suspendOrTerminate; - } - - public Supplier getNodeSupplier() { - return nodeSupplier; - } -} \ No newline at end of file + private final String cloudName; + private final String templateName; + private final int count; + private final boolean suspendOrTerminate; + private final Supplier nodeSupplier; + + public NodePlan(String cloud, String template, int count, boolean suspendOrTerminate, Supplier nodeSupplier) { + this.cloudName = cloud; + this.templateName = template; + this.count = count; + this.suspendOrTerminate = suspendOrTerminate; + this.nodeSupplier = nodeSupplier; + } + + public String getCloudName() { + return cloudName; + } + + public String getTemplateName() { + return templateName; + } + + public int getCount() { + return count; + } + + public boolean isSuspendOrTerminate() { + return suspendOrTerminate; + } + + public Supplier getNodeSupplier() { + return nodeSupplier; + } +} diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/ProvisionPlannedInstancesAndDestroyAllOnError.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/ProvisionPlannedInstancesAndDestroyAllOnError.java index badf61bd..e9700dc3 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/ProvisionPlannedInstancesAndDestroyAllOnError.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/ProvisionPlannedInstancesAndDestroyAllOnError.java @@ -14,66 +14,66 @@ import shaded.com.google.common.util.concurrent.ListeningExecutorService; public class ProvisionPlannedInstancesAndDestroyAllOnError implements Function, Iterable> { - private final ListeningExecutorService executor; - private final Logger logger; - private final Function, Void> terminateNodes; + private final ListeningExecutorService executor; + private final Logger logger; + private final Function, Void> terminateNodes; - public ProvisionPlannedInstancesAndDestroyAllOnError(ListeningExecutorService executor, Logger logger, Function, Void> terminateNodes) { - this.executor = executor; - this.logger = logger; - this.terminateNodes = terminateNodes; - } + public ProvisionPlannedInstancesAndDestroyAllOnError(ListeningExecutorService executor, Logger logger, Function, Void> terminateNodes) { + this.executor = executor; + this.logger = logger; + this.terminateNodes = terminateNodes; + } - public Iterable apply(Iterable nodePlans) { - final ImmutableList.Builder cloudTemplateNodeBuilder = ImmutableList. builder(); + public Iterable apply(Iterable nodePlans) { + final ImmutableList.Builder cloudTemplateNodeBuilder = ImmutableList.builder(); - final ImmutableList.Builder> plannedInstancesBuilder = ImmutableList.> builder(); + final ImmutableList.Builder> plannedInstancesBuilder = ImmutableList.>builder(); - final AtomicInteger failedLaunches = new AtomicInteger(); + final AtomicInteger failedLaunches = new AtomicInteger(); - for (final NodePlan nodePlan : nodePlans) { - for (int i = 0; i < nodePlan.getCount(); i++) { - final int index = i; - logger.info("Queuing cloud instance: #%d %d, %s %s", index, nodePlan.getCount(), nodePlan.getCloudName(), nodePlan.getTemplateName()); + for (final NodePlan nodePlan : nodePlans) { + for (int i = 0; i < nodePlan.getCount(); i++) { + final int index = i; + logger.info("Queuing cloud instance: #%d %d, %s %s", index, nodePlan.getCount(), nodePlan.getCloudName(), nodePlan.getTemplateName()); - ListenableFuture provisionTemplate = executor.submit(new RetrySupplierOnException(nodePlan.getNodeSupplier(), logger)); + ListenableFuture provisionTemplate = executor.submit(new RetrySupplierOnException(nodePlan.getNodeSupplier(), logger)); - Futures.addCallback(provisionTemplate, new FutureCallback() { - public void onSuccess(NodeMetadata result) { - if (result != null) { - cloudTemplateNodeBuilder.add(new RunningNode(nodePlan.getCloudName(), nodePlan.getTemplateName(), nodePlan.isSuspendOrTerminate(), - result)); - } else { - failedLaunches.incrementAndGet(); - } - } + Futures.addCallback(provisionTemplate, new FutureCallback() { + public void onSuccess(NodeMetadata result) { + if (result != null) { + cloudTemplateNodeBuilder.add(new RunningNode(nodePlan.getCloudName(), nodePlan.getTemplateName(), nodePlan.isSuspendOrTerminate(), + result)); + } else { + failedLaunches.incrementAndGet(); + } + } - public void onFailure(Throwable t) { - failedLaunches.incrementAndGet(); - logger.warn(t, "Error while launching instance: #%d %d, %s %s", index, nodePlan.getCount(), nodePlan.getCloudName(), - nodePlan.getTemplateName()); - } - }); + public void onFailure(Throwable t) { + failedLaunches.incrementAndGet(); + logger.warn(t, "Error while launching instance: #%d %d, %s %s", index, nodePlan.getCount(), nodePlan.getCloudName(), + nodePlan.getTemplateName()); + } + }); - plannedInstancesBuilder.add(provisionTemplate); + plannedInstancesBuilder.add(provisionTemplate); - } - } + } + } - // block until all complete - List nodesActuallyLaunched = Futures.getUnchecked(Futures.successfulAsList(plannedInstancesBuilder.build())); + // block until all complete + List nodesActuallyLaunched = Futures.getUnchecked(Futures.successfulAsList(plannedInstancesBuilder.build())); - final ImmutableList cloudTemplateNodes = cloudTemplateNodeBuilder.build(); + final ImmutableList cloudTemplateNodes = cloudTemplateNodeBuilder.build(); - assert cloudTemplateNodes.size() == nodesActuallyLaunched.size() : String.format( - "expected nodes from callbacks to be the same count as those from the list of futures!%n" + "fromCallbacks:%s%nfromFutures%s%n", - cloudTemplateNodes, nodesActuallyLaunched); + assert cloudTemplateNodes.size() == nodesActuallyLaunched.size() : String.format( + "expected nodes from callbacks to be the same count as those from the list of futures!%n" + "fromCallbacks:%s%nfromFutures%s%n", + cloudTemplateNodes, nodesActuallyLaunched); - if (failedLaunches.get() > 0) { - terminateNodes.apply(cloudTemplateNodes); - throw new IllegalStateException("One or more instances failed to launch."); - } - return cloudTemplateNodes; - } + if (failedLaunches.get() > 0) { + terminateNodes.apply(cloudTemplateNodes); + throw new IllegalStateException("One or more instances failed to launch."); + } + return cloudTemplateNodes; + } -} \ No newline at end of file +} diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RetrySupplierOnException.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RetrySupplierOnException.java index 4d887f9d..68455c2b 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RetrySupplierOnException.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RetrySupplierOnException.java @@ -8,32 +8,32 @@ import shaded.com.google.common.base.Supplier; class RetrySupplierOnException implements Callable { - private final int MAX_ATTEMPTS = 5; - private final Logger logger; - private final Supplier supplier; - - RetrySupplierOnException(Supplier supplier, Logger logger) { - this.supplier = supplier; - this.logger = logger; - } - - public NodeMetadata call() throws Exception { - int attempts = 0; - - while (attempts < MAX_ATTEMPTS) { - attempts++; - try { - NodeMetadata n = supplier.get(); - if (n != null) { - return n; - } - } catch (RuntimeException e) { - logger.warn("Exception creating a node: " + e.getMessage()); - // Something to log the e.getCause() which should be a - // RunNodesException - } - } - - return null; - } -} \ No newline at end of file + private final int MAX_ATTEMPTS = 5; + private final Logger logger; + private final Supplier supplier; + + RetrySupplierOnException(Supplier supplier, Logger logger) { + this.supplier = supplier; + this.logger = logger; + } + + public NodeMetadata call() throws Exception { + int attempts = 0; + + while (attempts < MAX_ATTEMPTS) { + attempts++; + try { + NodeMetadata n = supplier.get(); + if (n != null) { + return n; + } + } catch (RuntimeException e) { + logger.warn("Exception creating a node: " + e.getMessage()); + // Something to log the e.getCause() which should be a + // RunNodesException + } + } + + return null; + } +} diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RunningNode.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RunningNode.java index 12f7aa75..9ecadadd 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RunningNode.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/RunningNode.java @@ -3,31 +3,31 @@ import org.jclouds.compute.domain.NodeMetadata; public class RunningNode { - private final String cloud; - private final String template; - private final boolean suspendOrTerminate; - private final NodeMetadata node; + private final String cloud; + private final String template; + private final boolean suspendOrTerminate; + private final NodeMetadata node; - public RunningNode(String cloud, String template, boolean suspendOrTerminate, NodeMetadata node) { - this.cloud = cloud; - this.template = template; - this.suspendOrTerminate = suspendOrTerminate; - this.node = node; - } + public RunningNode(String cloud, String template, boolean suspendOrTerminate, NodeMetadata node) { + this.cloud = cloud; + this.template = template; + this.suspendOrTerminate = suspendOrTerminate; + this.node = node; + } - public String getCloudName() { - return cloud; - } + public String getCloudName() { + return cloud; + } - public String getTemplateName() { - return template; - } + public String getTemplateName() { + return template; + } - public boolean isSuspendOrTerminate() { - return suspendOrTerminate; - } + public boolean isSuspendOrTerminate() { + return suspendOrTerminate; + } - public NodeMetadata getNode() { - return node; - } -} \ No newline at end of file + public NodeMetadata getNode() { + return node; + } +} diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/TerminateNodes.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/TerminateNodes.java index a1e4e9a1..06eeef2e 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/TerminateNodes.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/TerminateNodes.java @@ -14,61 +14,61 @@ import shaded.com.google.common.collect.ImmutableMultimap.Builder; public class TerminateNodes implements Function, Void> { - private final Logger logger; - private final LoadingCache computeCache; + private final Logger logger; + private final LoadingCache computeCache; - public TerminateNodes(Logger logger, LoadingCache computeCache) { - this.logger = logger; - this.computeCache = computeCache; - } + public TerminateNodes(Logger logger, LoadingCache computeCache) { + this.logger = logger; + this.computeCache = computeCache; + } - public Void apply(Iterable runningNode) { - Builder cloudNodesToSuspendBuilder = ImmutableMultimap. builder(); - Builder cloudNodesToDestroyBuilder = ImmutableMultimap. builder(); - for (RunningNode cloudTemplateNode : runningNode) { - if (cloudTemplateNode.isSuspendOrTerminate()) { - cloudNodesToSuspendBuilder.put(cloudTemplateNode.getCloudName(), cloudTemplateNode.getNode().getId()); - } else { - cloudNodesToDestroyBuilder.put(cloudTemplateNode.getCloudName(), cloudTemplateNode.getNode().getId()); - } - } - Multimap cloudNodesToSuspend = cloudNodesToSuspendBuilder.build(); - Multimap cloudNodesToDestroy = cloudNodesToDestroyBuilder.build(); + public Void apply(Iterable runningNode) { + Builder cloudNodesToSuspendBuilder = ImmutableMultimap.builder(); + Builder cloudNodesToDestroyBuilder = ImmutableMultimap.builder(); + for (RunningNode cloudTemplateNode : runningNode) { + if (cloudTemplateNode.isSuspendOrTerminate()) { + cloudNodesToSuspendBuilder.put(cloudTemplateNode.getCloudName(), cloudTemplateNode.getNode().getId()); + } else { + cloudNodesToDestroyBuilder.put(cloudTemplateNode.getCloudName(), cloudTemplateNode.getNode().getId()); + } + } + Multimap cloudNodesToSuspend = cloudNodesToSuspendBuilder.build(); + Multimap cloudNodesToDestroy = cloudNodesToDestroyBuilder.build(); - suspendIfSupported(cloudNodesToSuspend); - destroy(cloudNodesToDestroy); - return null; - } + suspendIfSupported(cloudNodesToSuspend); + destroy(cloudNodesToDestroy); + return null; + } - private void destroy(Multimap cloudNodesToDestroy) { - for (String cloudToDestroy : cloudNodesToDestroy.keySet()) { - final Collection nodesToDestroy = cloudNodesToDestroy.get(cloudToDestroy); - logger.info("Destroying nodes: " + nodesToDestroy); - computeCache.getUnchecked(cloudToDestroy).destroyNodesMatching(new Predicate() { + private void destroy(Multimap cloudNodesToDestroy) { + for (String cloudToDestroy : cloudNodesToDestroy.keySet()) { + final Collection nodesToDestroy = cloudNodesToDestroy.get(cloudToDestroy); + logger.info("Destroying nodes: " + nodesToDestroy); + computeCache.getUnchecked(cloudToDestroy).destroyNodesMatching(new Predicate() { - public boolean apply(NodeMetadata input) { - return nodesToDestroy.contains(input.getId()); - } + public boolean apply(NodeMetadata input) { + return nodesToDestroy.contains(input.getId()); + } - }); - } - } + }); + } + } - private void suspendIfSupported(Multimap cloudNodesToSuspend) { - for (String cloudToSuspend : cloudNodesToSuspend.keySet()) { - final Collection nodesToSuspend = cloudNodesToSuspend.get(cloudToSuspend); - try { - logger.info("Suspending nodes: " + nodesToSuspend); - computeCache.getUnchecked(cloudToSuspend).suspendNodesMatching(new Predicate() { + private void suspendIfSupported(Multimap cloudNodesToSuspend) { + for (String cloudToSuspend : cloudNodesToSuspend.keySet()) { + final Collection nodesToSuspend = cloudNodesToSuspend.get(cloudToSuspend); + try { + logger.info("Suspending nodes: " + nodesToSuspend); + computeCache.getUnchecked(cloudToSuspend).suspendNodesMatching(new Predicate() { - public boolean apply(NodeMetadata input) { - return nodesToSuspend.contains(input.getId()); - } + public boolean apply(NodeMetadata input) { + return nodesToSuspend.contains(input.getId()); + } - }); - } catch (UnsupportedOperationException e) { - logger.info("Suspending unsupported on cloud: " + cloudToSuspend + "; nodes: " + nodesToSuspend + ": " + e); - } - } - } -} \ No newline at end of file + }); + } catch (UnsupportedOperationException e) { + logger.info("Suspending unsupported on cloud: " + cloudToSuspend + "; nodes: " + nodesToSuspend + ": " + e); + } + } + } +} diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/package-info.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/package-info.java index a3d033ae..95e03663 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/package-info.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/compute/internal/package-info.java @@ -1,5 +1,5 @@ /** * Code written in POJO style to facilitate unit testing - * + * */ -package jenkins.plugins.jclouds.compute.internal; \ No newline at end of file +package jenkins.plugins.jclouds.compute.internal; diff --git a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/internal/BuildListenerLogger.java b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/internal/BuildListenerLogger.java index f5bf994f..47b5b5a8 100644 --- a/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/internal/BuildListenerLogger.java +++ b/jclouds-plugin/src/main/java/jenkins/plugins/jclouds/internal/BuildListenerLogger.java @@ -3,61 +3,61 @@ import hudson.model.BuildListener; public class BuildListenerLogger implements org.jclouds.logging.Logger { - private final BuildListener listener; + private final BuildListener listener; - public BuildListenerLogger(BuildListener listener) { - this.listener = listener; - } + public BuildListenerLogger(BuildListener listener) { + this.listener = listener; + } - public void debug(String message, Object... args) { - // noop - } + public void debug(String message, Object... args) { + // noop + } - public void error(String message, Object... args) { - listener.fatalError(String.format(message, args)); - } + public void error(String message, Object... args) { + listener.fatalError(String.format(message, args)); + } - public void error(Throwable throwable, String message, Object... args) { - listener.fatalError(String.format(message, args) + ": " + throwable.getCause()); - } + public void error(Throwable throwable, String message, Object... args) { + listener.fatalError(String.format(message, args) + ": " + throwable.getCause()); + } - public String getCategory() { - return null; - } + public String getCategory() { + return null; + } - public void info(String message, Object... args) { - listener.getLogger().println(String.format(message, args)); - } + public void info(String message, Object... args) { + listener.getLogger().println(String.format(message, args)); + } - public boolean isDebugEnabled() { - return false; - } + public boolean isDebugEnabled() { + return false; + } - public boolean isErrorEnabled() { - return true; - } + public boolean isErrorEnabled() { + return true; + } - public boolean isInfoEnabled() { - return true; - } + public boolean isInfoEnabled() { + return true; + } - public boolean isTraceEnabled() { - return false; - } + public boolean isTraceEnabled() { + return false; + } - public boolean isWarnEnabled() { - return true; - } + public boolean isWarnEnabled() { + return true; + } - public void trace(String message, Object... args) { - } + public void trace(String message, Object... args) { + } - public void warn(String message, Object... args) { - listener.error(String.format(message, args)); - } + public void warn(String message, Object... args) { + listener.error(String.format(message, args)); + } - public void warn(Throwable throwable, String message, Object... args) { - listener.error(String.format(message, args) + ": " + throwable.getCause()); - } + public void warn(Throwable throwable, String message, Object... args) { + listener.error(String.format(message, args) + ": " + throwable.getCause()); + } -} \ No newline at end of file +} diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileInsideJenkinsLiveTest.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileInsideJenkinsLiveTest.java index daad50af..488bf792 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileInsideJenkinsLiveTest.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileInsideJenkinsLiveTest.java @@ -4,36 +4,36 @@ public class BlobStoreProfileInsideJenkinsLiveTest extends HudsonTestCase { - private BlobStoreTestFixture fixture; - private BlobStoreProfile profile; - - @Override - public void setUp() throws Exception { - super.setUp(); - fixture = new BlobStoreTestFixture(); - fixture.setUp(); - - // TODO: this may need to vary per test - profile = new BlobStoreProfile(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential()); - } - - public static final String CONTAINER_PREFIX = System.getProperty("user.name") + "-blobstore-profile"; - - public void testUpload() { - String container = CONTAINER_PREFIX + "-upload"; - try { - fixture.getBlobStore().createContainerInLocation(null, container); - // filePath == ?? - // profile.upload(container, filePath) - // assertTrue(fixture.getBlobStore().blobExists(container, filename)); - } finally { - fixture.getBlobStore().deleteContainer(container); - } - } - - @Override - public void tearDown() { - if (fixture != null) - fixture.tearDown(); - } -} \ No newline at end of file + private BlobStoreTestFixture fixture; + private BlobStoreProfile profile; + + @Override + public void setUp() throws Exception { + super.setUp(); + fixture = new BlobStoreTestFixture(); + fixture.setUp(); + + // TODO: this may need to vary per test + profile = new BlobStoreProfile(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential()); + } + + public static final String CONTAINER_PREFIX = System.getProperty("user.name") + "-blobstore-profile"; + + public void testUpload() { + String container = CONTAINER_PREFIX + "-upload"; + try { + fixture.getBlobStore().createContainerInLocation(null, container); + // filePath == ?? + // profile.upload(container, filePath) + // assertTrue(fixture.getBlobStore().blobExists(container, filename)); + } finally { + fixture.getBlobStore().deleteContainer(container); + } + } + + @Override + public void tearDown() { + if (fixture != null) + fixture.tearDown(); + } +} diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileLiveTest.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileLiveTest.java index fd76e095..409bbca7 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileLiveTest.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreProfileLiveTest.java @@ -4,36 +4,36 @@ public class BlobStoreProfileLiveTest extends TestCase { - private BlobStoreTestFixture fixture; - private BlobStoreProfile profile; - - @Override - public void setUp() throws Exception { - super.setUp(); - fixture = new BlobStoreTestFixture(); - fixture.setUp(); - - // TODO: this may need to vary per test - profile = new BlobStoreProfile(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential()); - } - - public static final String CONTAINER_PREFIX = System.getProperty("user.name") + "-blobstore-profile"; - - public void testUpload() { - String container = CONTAINER_PREFIX + "-upload"; - try { - fixture.getBlobStore().createContainerInLocation(null, container); - // filePath == ?? - // profile.upload(container, filePath) - // assertTrue(fixture.getBlobStore().blobExists(container, filename)); - } finally { - fixture.getBlobStore().deleteContainer(container); - } - } - - @Override - public void tearDown() { - if (fixture != null) - fixture.tearDown(); - } -} \ No newline at end of file + private BlobStoreTestFixture fixture; + private BlobStoreProfile profile; + + @Override + public void setUp() throws Exception { + super.setUp(); + fixture = new BlobStoreTestFixture(); + fixture.setUp(); + + // TODO: this may need to vary per test + profile = new BlobStoreProfile(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential()); + } + + public static final String CONTAINER_PREFIX = System.getProperty("user.name") + "-blobstore-profile"; + + public void testUpload() { + String container = CONTAINER_PREFIX + "-upload"; + try { + fixture.getBlobStore().createContainerInLocation(null, container); + // filePath == ?? + // profile.upload(container, filePath) + // assertTrue(fixture.getBlobStore().blobExists(container, filename)); + } finally { + fixture.getBlobStore().deleteContainer(container); + } + } + + @Override + public void tearDown() { + if (fixture != null) + fixture.tearDown(); + } +} diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreTestFixture.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreTestFixture.java index d957e8e7..b824b701 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreTestFixture.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/blobstore/BlobStoreTestFixture.java @@ -16,74 +16,74 @@ @SuppressWarnings("unchecked") public class BlobStoreTestFixture extends BaseViewLiveTest { - public static String PROVIDER; - - /** - * base jclouds tests expect properties to arrive in a different naming convention, based on provider name. - * - * ex. - * - *

-	 *  test.jenkins.blobstore.provider=aws-s3
-	 *  test.jenkins.blobstore.identity=access
-	 *  test.jenkins.blobstore.credential=secret
-	 * 
- * - * should turn into - * - *
-	 *  test.aws-s3.identity=access
-	 *  test.aws-s3.credential=secret
-	 * 
- */ - static { - PROVIDER = checkNotNull(System.getProperty("test.jenkins.blobstore.provider"), "test.blobstore.provider variable must be set!"); - Map filtered = Maps.filterKeys(Map.class.cast(System.getProperties()), Predicates.containsPattern("^test\\.jenkins\\.blobstore")); - Map transformed = Maps2.transformKeys(filtered, new Function() { - - public String apply(String arg0) { - return arg0.replaceAll("test.jenkins.blobstore", "test." + PROVIDER); - } - - }); - System.getProperties().putAll(transformed); - } - - public BlobStoreTestFixture() { - provider = PROVIDER; - } - - public BlobStore getBlobStore() { - return view.getBlobStore(); - } - - public String getProvider() { - return provider; - } - - public String getEndpoint() { - return endpoint; - } - - public String getIdentity() { - return identity; - } - - public String getCredential() { - return credential; - } - - public void setUp() { - super.setupContext(); - } - - public void tearDown() { - super.tearDownContext(); - } - - @Override - protected TypeToken viewType() { - return TypeToken.of(BlobStoreContext.class); - } + public static String PROVIDER; + + /** + * base jclouds tests expect properties to arrive in a different naming convention, based on provider name. + * + * ex. + * + *
+     *  test.jenkins.blobstore.provider=aws-s3
+     *  test.jenkins.blobstore.identity=access
+     *  test.jenkins.blobstore.credential=secret
+     * 
+ * + * should turn into + * + *
+     *  test.aws-s3.identity=access
+     *  test.aws-s3.credential=secret
+     * 
+ */ + static { + PROVIDER = checkNotNull(System.getProperty("test.jenkins.blobstore.provider"), "test.blobstore.provider variable must be set!"); + Map filtered = Maps.filterKeys(Map.class.cast(System.getProperties()), Predicates.containsPattern("^test\\.jenkins\\.blobstore")); + Map transformed = Maps2.transformKeys(filtered, new Function() { + + public String apply(String arg0) { + return arg0.replaceAll("test.jenkins.blobstore", "test." + PROVIDER); + } + + }); + System.getProperties().putAll(transformed); + } + + public BlobStoreTestFixture() { + provider = PROVIDER; + } + + public BlobStore getBlobStore() { + return view.getBlobStore(); + } + + public String getProvider() { + return provider; + } + + public String getEndpoint() { + return endpoint; + } + + public String getIdentity() { + return identity; + } + + public String getCredential() { + return credential; + } + + public void setUp() { + super.setupContext(); + } + + public void tearDown() { + super.tearDownContext(); + } + + @Override + protected TypeToken viewType() { + return TypeToken.of(BlobStoreContext.class); + } } diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/ComputeTestFixture.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/ComputeTestFixture.java index 66b10a11..1bcd109c 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/ComputeTestFixture.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/ComputeTestFixture.java @@ -16,74 +16,74 @@ @SuppressWarnings("unchecked") public class ComputeTestFixture extends BaseComputeServiceContextLiveTest { - public static String PROVIDER; - - /** - * base jclouds tests expect properties to arrive in a different naming convention, based on provider name. - * - * ex. - * - *
-	 *  test.jenkins.compute.provider=aws-ec2
-	 *  test.jenkins.compute.identity=access
-	 *  test.jenkins.compute.credential=secret
-	 * 
- * - * should turn into - * - *
-	 *  test.aws-ec2.identity=access
-	 *  test.aws-ec2.credential=secret
-	 * 
- */ - static { - PROVIDER = checkNotNull(System.getProperty("test.jenkins.compute.provider"), "test.compute.provider variable must be set!"); - Map filtered = Maps.filterKeys(Map.class.cast(System.getProperties()), Predicates.containsPattern("^test\\.jenkins\\.compute")); - Map transformed = Maps2.transformKeys(filtered, new Function() { - - public String apply(String arg0) { - return arg0.replaceAll("test.jenkins.compute", "test." + PROVIDER); - } - - }); - System.getProperties().putAll(transformed); - } - - public ComputeTestFixture() { - provider = PROVIDER; - } - - @Override - protected Module getSshModule() { - return new SshjSshClientModule(); - } - - public ComputeService getComputeService() { - return view.getComputeService(); - } - - public String getProvider() { - return provider; - } - - public String getEndpoint() { - return endpoint; - } - - public String getIdentity() { - return identity; - } - - public String getCredential() { - return credential; - } - - public void setUp() { - super.setupContext(); - } - - public void tearDown() { - super.tearDownContext(); - } + public static String PROVIDER; + + /** + * base jclouds tests expect properties to arrive in a different naming convention, based on provider name. + * + * ex. + * + *
+     *  test.jenkins.compute.provider=aws-ec2
+     *  test.jenkins.compute.identity=access
+     *  test.jenkins.compute.credential=secret
+     * 
+ * + * should turn into + * + *
+     *  test.aws-ec2.identity=access
+     *  test.aws-ec2.credential=secret
+     * 
+ */ + static { + PROVIDER = checkNotNull(System.getProperty("test.jenkins.compute.provider"), "test.compute.provider variable must be set!"); + Map filtered = Maps.filterKeys(Map.class.cast(System.getProperties()), Predicates.containsPattern("^test\\.jenkins\\.compute")); + Map transformed = Maps2.transformKeys(filtered, new Function() { + + public String apply(String arg0) { + return arg0.replaceAll("test.jenkins.compute", "test." + PROVIDER); + } + + }); + System.getProperties().putAll(transformed); + } + + public ComputeTestFixture() { + provider = PROVIDER; + } + + @Override + protected Module getSshModule() { + return new SshjSshClientModule(); + } + + public ComputeService getComputeService() { + return view.getComputeService(); + } + + public String getProvider() { + return provider; + } + + public String getEndpoint() { + return endpoint; + } + + public String getIdentity() { + return identity; + } + + public String getCredential() { + return credential; + } + + public void setUp() { + super.setupContext(); + } + + public void tearDown() { + super.tearDownContext(); + } } diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudInsideJenkinsLiveTest.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudInsideJenkinsLiveTest.java index 3b5c06d4..9bb38dfd 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudInsideJenkinsLiveTest.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudInsideJenkinsLiveTest.java @@ -11,32 +11,32 @@ public class JCloudsCloudInsideJenkinsLiveTest extends HudsonTestCase { - private ComputeTestFixture fixture; - private JCloudsCloud cloud; - private Map generatedKeys; - - @Override - public void setUp() throws Exception { - super.setUp(); - fixture = new ComputeTestFixture(); - fixture.setUp(); - generatedKeys = SshKeys.generate(); - - // TODO: this may need to vary per test - cloud = new JCloudsCloud(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), - generatedKeys.get("private"), generatedKeys.get("public"), fixture.getEndpoint(), 1, 30, 600 * 1000, 600 * 1000, null, - Collections. emptyList()); - } - - public void testDoTestConnectionCorrectCredentialsEtc () throws IOException { - FormValidation result = new JCloudsCloud.DescriptorImpl().doTestConnection(fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), - generatedKeys.get("private"), fixture.getEndpoint(), null); - assertEquals("Connection succeeded!", result.getMessage()); - } - - @Override - public void tearDown() { - if (fixture != null) - fixture.tearDown(); - } -} \ No newline at end of file + private ComputeTestFixture fixture; + private JCloudsCloud cloud; + private Map generatedKeys; + + @Override + public void setUp() throws Exception { + super.setUp(); + fixture = new ComputeTestFixture(); + fixture.setUp(); + generatedKeys = SshKeys.generate(); + + // TODO: this may need to vary per test + cloud = new JCloudsCloud(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), + generatedKeys.get("private"), generatedKeys.get("public"), fixture.getEndpoint(), 1, 30, 600 * 1000, 600 * 1000, null, + Collections.emptyList()); + } + + public void testDoTestConnectionCorrectCredentialsEtc() throws IOException { + FormValidation result = new JCloudsCloud.DescriptorImpl().doTestConnection(fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), + generatedKeys.get("private"), fixture.getEndpoint(), null); + assertEquals("Connection succeeded!", result.getMessage()); + } + + @Override + public void tearDown() { + if (fixture != null) + fixture.tearDown(); + } +} diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudLiveTest.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudLiveTest.java index 3defd13d..45896510 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudLiveTest.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudLiveTest.java @@ -12,32 +12,32 @@ public class JCloudsCloudLiveTest extends TestCase { - private ComputeTestFixture fixture; - private JCloudsCloud cloud; - private Map generatedKeys; - - @Override - public void setUp() throws Exception { - super.setUp(); - fixture = new ComputeTestFixture(); - fixture.setUp(); - generatedKeys = SshKeys.generate(); - - // TODO: this may need to vary per test - cloud = new JCloudsCloud(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), - generatedKeys.get("private"), generatedKeys.get("public"), fixture.getEndpoint(), 1, 30, 600 * 1000, 600 * 1000, null, - Collections. emptyList()); - } - - public void testDoTestConnectionCorrectCredentialsEtc() throws IOException { - FormValidation result = new JCloudsCloud.DescriptorImpl().doTestConnection(fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), - generatedKeys.get("private"), fixture.getEndpoint(), null); - assertEquals("Connection succeeded!", result.getMessage()); - } - - @Override - public void tearDown() { - if (fixture != null) - fixture.tearDown(); - } -} \ No newline at end of file + private ComputeTestFixture fixture; + private JCloudsCloud cloud; + private Map generatedKeys; + + @Override + public void setUp() throws Exception { + super.setUp(); + fixture = new ComputeTestFixture(); + fixture.setUp(); + generatedKeys = SshKeys.generate(); + + // TODO: this may need to vary per test + cloud = new JCloudsCloud(fixture.getProvider() + "-profile", fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), + generatedKeys.get("private"), generatedKeys.get("public"), fixture.getEndpoint(), 1, 30, 600 * 1000, 600 * 1000, null, + Collections.emptyList()); + } + + public void testDoTestConnectionCorrectCredentialsEtc() throws IOException { + FormValidation result = new JCloudsCloud.DescriptorImpl().doTestConnection(fixture.getProvider(), fixture.getIdentity(), fixture.getCredential(), + generatedKeys.get("private"), fixture.getEndpoint(), null); + assertEquals("Connection succeeded!", result.getMessage()); + } + + @Override + public void tearDown() { + if (fixture != null) + fixture.tearDown(); + } +} diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudTest.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudTest.java index 8ceeff2d..606c7268 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudTest.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsCloudTest.java @@ -21,52 +21,52 @@ public class JCloudsCloudTest { public JenkinsRule j = new JenkinsRule(); @Test - public void testConfigurationUI() throws Exception { + public void testConfigurationUI() throws Exception { j.recipeLoadCurrentPlugin(); j.configRoundtrip(); - HtmlPage page = j.createWebClient().goTo("configure"); - final String pageText = page.asText(); - assertTrue("Cloud Section must be present in the global configuration ", pageText.contains("Cloud")); + HtmlPage page = j.createWebClient().goTo("configure"); + final String pageText = page.asText(); + assertTrue("Cloud Section must be present in the global configuration ", pageText.contains("Cloud")); - final HtmlForm configForm = page.getFormByName("config"); - final HtmlButton buttonByCaption = configForm.getButtonByCaption("Add a new cloud"); - HtmlPage page1 = buttonByCaption.click(); - WebAssert.assertLinkPresentWithText(page1, "Cloud (JClouds)"); + final HtmlForm configForm = page.getFormByName("config"); + final HtmlButton buttonByCaption = configForm.getButtonByCaption("Add a new cloud"); + HtmlPage page1 = buttonByCaption.click(); + WebAssert.assertLinkPresentWithText(page1, "Cloud (JClouds)"); - HtmlPage page2 = page.getAnchorByText("Cloud (JClouds)").click(); - WebAssert.assertInputPresent(page2, "_.profile"); - WebAssert.assertInputPresent(page2, "_.endPointUrl"); - WebAssert.assertInputPresent(page2, "_.identity"); - WebAssert.assertInputPresent(page2, "_.credential"); - WebAssert.assertInputPresent(page2, "_.instanceCap"); - WebAssert.assertInputPresent(page2, "_.retentionTime"); + HtmlPage page2 = page.getAnchorByText("Cloud (JClouds)").click(); + WebAssert.assertInputPresent(page2, "_.profile"); + WebAssert.assertInputPresent(page2, "_.endPointUrl"); + WebAssert.assertInputPresent(page2, "_.identity"); + WebAssert.assertInputPresent(page2, "_.credential"); + WebAssert.assertInputPresent(page2, "_.instanceCap"); + WebAssert.assertInputPresent(page2, "_.retentionTime"); - HtmlForm configForm2 = page2.getFormByName("config"); - assertNotNull(configForm2.getTextAreaByName("_.privateKey")); - assertNotNull(configForm2.getTextAreaByName("_.publicKey")); - HtmlButton generateKeyPairButton = configForm2.getButtonByCaption("Generate Key Pair"); - HtmlButton testConnectionButton = configForm2.getButtonByCaption("Test Connection"); - HtmlButton deleteCloudButton = configForm2.getButtonByCaption("Delete cloud"); - assertNotNull(generateKeyPairButton); - assertNotNull(testConnectionButton); - assertNotNull(deleteCloudButton); + HtmlForm configForm2 = page2.getFormByName("config"); + assertNotNull(configForm2.getTextAreaByName("_.privateKey")); + assertNotNull(configForm2.getTextAreaByName("_.publicKey")); + HtmlButton generateKeyPairButton = configForm2.getButtonByCaption("Generate Key Pair"); + HtmlButton testConnectionButton = configForm2.getButtonByCaption("Test Connection"); + HtmlButton deleteCloudButton = configForm2.getButtonByCaption("Delete cloud"); + assertNotNull(generateKeyPairButton); + assertNotNull(testConnectionButton); + assertNotNull(deleteCloudButton); - } + } @Test - public void testConfigRoundtrip() throws Exception { + public void testConfigRoundtrip() throws Exception { - JCloudsCloud original = new JCloudsCloud("aws-profile", "aws-ec2", "identity", "credential", "privateKey", "publicKey", "endPointUrl", 1, 30, - 600 * 1000, 600 * 1000, null, Collections. emptyList()); + JCloudsCloud original = new JCloudsCloud("aws-profile", "aws-ec2", "identity", "credential", "privateKey", "publicKey", "endPointUrl", 1, 30, + 600 * 1000, 600 * 1000, null, Collections.emptyList()); - j.getInstance().clouds.add(original); + j.getInstance().clouds.add(original); j.submit(j.createWebClient().goTo("configure").getFormByName("config")); - j.assertEqualBeans(original, j.getInstance().clouds.getByName("aws-profile"), - "profile,providerName,identity,credential,privateKey,publicKey,endPointUrl,instanceCap,retentionTime"); + j.assertEqualBeans(original, j.getInstance().clouds.getByName("aws-profile"), + "profile,providerName,identity,credential,privateKey,publicKey,endPointUrl,instanceCap,retentionTime"); - j.assertEqualBeans(original, JCloudsCloud.getByName("aws-profile"), - "profile,providerName,identity,credential,privateKey,publicKey,endPointUrl,instanceCap,retentionTime"); - } + j.assertEqualBeans(original, JCloudsCloud.getByName("aws-profile"), + "profile,providerName,identity,credential,privateKey,publicKey,endPointUrl,instanceCap,retentionTime"); + } } diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplateTest.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplateTest.java index 92759889..dde35577 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplateTest.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/JCloudsSlaveTemplateTest.java @@ -10,26 +10,26 @@ */ public class JCloudsSlaveTemplateTest extends HudsonTestCase { - public void testConfigRoundtrip() throws Exception { - String name = "testSlave"; - JCloudsSlaveTemplate originalTemplate = new JCloudsSlaveTemplate(name, "imageId", null, "hardwareId", 1, 512, "osFamily", "osVersion", "locationId", - "jclouds-slave-type1 jclouds-type2", "Description", "initScript", null, "1", false, null, null, true, "jenkins", null, false, null, false, - false, 5, 0, true, "jenkins", true, "network1_id,network2_id", "security_group1,security_group2"); + public void testConfigRoundtrip() throws Exception { + String name = "testSlave"; + JCloudsSlaveTemplate originalTemplate = new JCloudsSlaveTemplate(name, "imageId", null, "hardwareId", 1, 512, "osFamily", "osVersion", "locationId", + "jclouds-slave-type1 jclouds-type2", "Description", "initScript", null, "1", false, null, null, true, "jenkins", null, false, null, false, + false, 5, 0, true, "jenkins", true, "network1_id,network2_id", "security_group1,security_group2"); - List templates = new ArrayList(); - templates.add(originalTemplate); + List templates = new ArrayList(); + templates.add(originalTemplate); - JCloudsCloud originalCloud = new JCloudsCloud("aws-profile", "aws-ec2", "identity", "credential", "privateKey", "publicKey", "endPointUrl", 1, 30, - 600 * 1000, 600 * 1000, null, templates); + JCloudsCloud originalCloud = new JCloudsCloud("aws-profile", "aws-ec2", "identity", "credential", "privateKey", "publicKey", "endPointUrl", 1, 30, + 600 * 1000, 600 * 1000, null, templates); - hudson.clouds.add(originalCloud); - submit(createWebClient().goTo("configure").getFormByName("config")); + hudson.clouds.add(originalCloud); + submit(createWebClient().goTo("configure").getFormByName("config")); - assertEqualBeans(originalCloud, JCloudsCloud.getByName("aws-profile"), "profile,providerName,identity,credential,privateKey,publicKey,endPointUrl"); + assertEqualBeans(originalCloud, JCloudsCloud.getByName("aws-profile"), "profile,providerName,identity,credential,privateKey,publicKey,endPointUrl"); - assertEqualBeans(originalTemplate, JCloudsCloud.getByName("aws-profile").getTemplate(name), - "name,cores,ram,osFamily,osVersion,labelString,description,initScript,numExecutors,stopOnTerminate"); + assertEqualBeans(originalTemplate, JCloudsCloud.getByName("aws-profile").getTemplate(name), + "name,cores,ram,osFamily,osVersion,labelString,description,initScript,numExecutors,stopOnTerminate"); - } + } } diff --git a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/internal/TerminateNodesTest.java b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/internal/TerminateNodesTest.java index 53137219..499b5770 100644 --- a/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/internal/TerminateNodesTest.java +++ b/jclouds-plugin/src/test/java/jenkins/plugins/jclouds/compute/internal/TerminateNodesTest.java @@ -24,95 +24,95 @@ public class TerminateNodesTest extends TestCase { - private ComputeService compute; + private ComputeService compute; - @Override - protected void setUp() throws Exception { - compute = ContextBuilder.newBuilder("stub").buildView(ComputeServiceContext.class).getComputeService(); - } + @Override + protected void setUp() throws Exception { + compute = ContextBuilder.newBuilder("stub").buildView(ComputeServiceContext.class).getComputeService(); + } - public void testSuspendOnlySuspendsNodesInQuestion() throws InterruptedException, ExecutionException, RunNodesException { + public void testSuspendOnlySuspendsNodesInQuestion() throws InterruptedException, ExecutionException, RunNodesException { - List nodes = ImmutableList.copyOf(compute.createNodesInGroup("suspend", 10)); - List> split = Lists.partition(nodes, 5); + List nodes = ImmutableList.copyOf(compute.createNodesInGroup("suspend", 10)); + List> split = Lists.partition(nodes, 5); - Iterable runningNodesToSuspend = Iterables.transform(split.get(0), new Function() { + Iterable runningNodesToSuspend = Iterables.transform(split.get(0), new Function() { - public RunningNode apply(NodeMetadata input) { - return new RunningNode("stub", "template", true, input); - } + public RunningNode apply(NodeMetadata input) { + return new RunningNode("stub", "template", true, input); + } - }); + }); - newTerminateNodes(compute).apply(runningNodesToSuspend); + newTerminateNodes(compute).apply(runningNodesToSuspend); - for (NodeMetadata node : split.get(0)) - assertEquals(NodeMetadata.Status.SUSPENDED, compute.getNodeMetadata(node.getId()).getStatus()); - for (NodeMetadata node : split.get(1)) - assertEquals(NodeMetadata.Status.RUNNING, compute.getNodeMetadata(node.getId()).getStatus()); + for (NodeMetadata node : split.get(0)) + assertEquals(NodeMetadata.Status.SUSPENDED, compute.getNodeMetadata(node.getId()).getStatus()); + for (NodeMetadata node : split.get(1)) + assertEquals(NodeMetadata.Status.RUNNING, compute.getNodeMetadata(node.getId()).getStatus()); - } + } - private TerminateNodes newTerminateNodes(ComputeService compute) { - LoadingCache cache = CacheBuilder.newBuilder().build( - CacheLoader. from(Functions.forMap(ImmutableMap.of("stub", compute)))); - return new TerminateNodes(Logger.NULL, cache); - } + private TerminateNodes newTerminateNodes(ComputeService compute) { + LoadingCache cache = CacheBuilder.newBuilder().build( + CacheLoader.from(Functions.forMap(ImmutableMap.of("stub", compute)))); + return new TerminateNodes(Logger.NULL, cache); + } - public void testDestroyOnlyDestroysNodesInQuestion() throws InterruptedException, ExecutionException, RunNodesException { + public void testDestroyOnlyDestroysNodesInQuestion() throws InterruptedException, ExecutionException, RunNodesException { - List nodes = ImmutableList.copyOf(compute.createNodesInGroup("destroy", 10)); - List> split = Lists.partition(nodes, 5); + List nodes = ImmutableList.copyOf(compute.createNodesInGroup("destroy", 10)); + List> split = Lists.partition(nodes, 5); - Iterable runningNodesToDestroy = Iterables.transform(split.get(0), new Function() { + Iterable runningNodesToDestroy = Iterables.transform(split.get(0), new Function() { - public RunningNode apply(NodeMetadata input) { - return new RunningNode("stub", "template", false, input); - } + public RunningNode apply(NodeMetadata input) { + return new RunningNode("stub", "template", false, input); + } - }); + }); - newTerminateNodes(compute).apply(runningNodesToDestroy); + newTerminateNodes(compute).apply(runningNodesToDestroy); - for (NodeMetadata node : split.get(0)) - assertEquals(null, compute.getNodeMetadata(node.getId())); - for (NodeMetadata node : split.get(1)) - assertEquals(NodeMetadata.Status.RUNNING, compute.getNodeMetadata(node.getId()).getStatus()); + for (NodeMetadata node : split.get(0)) + assertEquals(null, compute.getNodeMetadata(node.getId())); + for (NodeMetadata node : split.get(1)) + assertEquals(NodeMetadata.Status.RUNNING, compute.getNodeMetadata(node.getId()).getStatus()); - } + } - public void testSuspendAndDestroy() throws InterruptedException, ExecutionException, RunNodesException { + public void testSuspendAndDestroy() throws InterruptedException, ExecutionException, RunNodesException { - List nodes = ImmutableList.copyOf(compute.createNodesInGroup("suspenddestroy", 10)); - List> split = Lists.partition(nodes, 5); + List nodes = ImmutableList.copyOf(compute.createNodesInGroup("suspenddestroy", 10)); + List> split = Lists.partition(nodes, 5); - Iterable runningNodesToSuspend = Iterables.transform(split.get(0), new Function() { + Iterable runningNodesToSuspend = Iterables.transform(split.get(0), new Function() { - public RunningNode apply(NodeMetadata input) { - return new RunningNode("stub", "template", true, input); - } + public RunningNode apply(NodeMetadata input) { + return new RunningNode("stub", "template", true, input); + } - }); + }); - Iterable runningNodesToDestroy = Iterables.transform(split.get(1), new Function() { + Iterable runningNodesToDestroy = Iterables.transform(split.get(1), new Function() { - public RunningNode apply(NodeMetadata input) { - return new RunningNode("stub", "template", false, input); - } + public RunningNode apply(NodeMetadata input) { + return new RunningNode("stub", "template", false, input); + } - }); + }); - newTerminateNodes(compute).apply(Iterables.concat(runningNodesToSuspend, runningNodesToDestroy)); + newTerminateNodes(compute).apply(Iterables.concat(runningNodesToSuspend, runningNodesToDestroy)); - for (NodeMetadata node : split.get(0)) - assertEquals(NodeMetadata.Status.SUSPENDED, compute.getNodeMetadata(node.getId()).getStatus()); - for (NodeMetadata node : split.get(1)) - assertEquals(null, compute.getNodeMetadata(node.getId())); + for (NodeMetadata node : split.get(0)) + assertEquals(NodeMetadata.Status.SUSPENDED, compute.getNodeMetadata(node.getId()).getStatus()); + for (NodeMetadata node : split.get(1)) + assertEquals(null, compute.getNodeMetadata(node.getId())); - } + } - @Override - protected void tearDown() throws Exception { - compute.getContext().close(); - } + @Override + protected void tearDown() throws Exception { + compute.getContext().close(); + } }