Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.offbytwo.jenkins.integration;

import com.offbytwo.jenkins.JenkinsServer;
import com.offbytwo.jenkins.model.Plugin;
import com.offbytwo.jenkins.model.credentials.*;
import org.apache.commons.lang.RandomStringUtils;
import org.testng.SkipException;
import org.testng.annotations.Test;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import static org.testng.Assert.*;

@Test(groups = { Groups.NO_EXECUTOR_GROUP} )
public class NoExecutorStartedManageCredentialsIT extends AbstractJenkinsIntegrationCase {

@Test
public void credentialCRUDL() throws IOException {
List<Plugin> plugins = jenkinsServer.getPluginManager().getPlugins();
Plugin credentialPlugin = jenkinsServer.findPluginWithName("credentials");
if (credentialPlugin == null) {
throw new SkipException("No credentials plugin found. Skip Test");
}

String pluginVersion = credentialPlugin.getVersion();
if (pluginVersion.startsWith("1.")) {
runTest(jenkinsServer);

//test CertificateCredential with upload cert file. The 2.x version may throw exceptions.
CertificateCredential certificateCredential = new CertificateCredential();
certificateCredential.setId("certficateTest-" + RandomStringUtils.randomAlphanumeric(24));
certificateCredential.setCertificateSourceType(CertificateCredential.CERTIFICATE_SOURCE_TYPES.UPLOAD_CERT_FILE);
certificateCredential.setCertificateContent("testcert".getBytes());
certificateCredential.setPassword("testpasssword");

credentialOperations(jenkinsServer, certificateCredential);

} else {
runTest(jenkinsServer);

//test SecretTextCredential, this is v2 only
SecretTextCredential secretText = new SecretTextCredential();
secretText.setId("secrettextcredentialTest-" + RandomStringUtils.randomAlphanumeric(24));
secretText.setSecret("testsecrettext");

credentialOperations(jenkinsServer, secretText);
}
}

private void runTest(JenkinsServer jenkinsServer) throws IOException {
String testUsername = "testusername";
String testPassword = "testpassword";
String credentialDescription = "testDescription";
//test UsernamePasswordCredential
UsernamePasswordCredential testUPCredential = new UsernamePasswordCredential();
testUPCredential.setId("usernamepasswordcredentialTest-" + RandomStringUtils.randomAlphanumeric(24));
testUPCredential.setUsername(testUsername);
testUPCredential.setPassword(testPassword);
testUPCredential.setDescription(credentialDescription);

credentialOperations(jenkinsServer, testUPCredential);

//test SSHKeyCredential
SSHKeyCredential sshCredential = new SSHKeyCredential();
sshCredential.setId("sshusercredentialTest-" + RandomStringUtils.randomAlphanumeric(24));
sshCredential.setUsername(testUsername);
sshCredential.setPassphrase(testPassword);
sshCredential.setPrivateKeyType(SSHKeyCredential.PRIVATE_KEY_TYPES.DIRECT_ENTRY);
sshCredential.setPrivateKeyValue("testPrivateKeyContent");

credentialOperations(jenkinsServer, sshCredential);

//test credential
CertificateCredential certificateCredential = new CertificateCredential();
certificateCredential.setId("certficateTest-" + RandomStringUtils.randomAlphanumeric(24));
certificateCredential.setCertificateSourceType(CertificateCredential.CERTIFICATE_SOURCE_TYPES.FILE_ON_MASTER);
certificateCredential.setCertificatePath("/tmp/test");
certificateCredential.setPassword("testpasssword");

credentialOperations(jenkinsServer, certificateCredential);

}

private void credentialOperations(JenkinsServer jenkinsServer, Credential credential) throws IOException {
//create the credential
String credentialId = credential.getId();
jenkinsServer.createCredential(credential, false);

//check if has been created by listing
Map<String, Credential> credentials = jenkinsServer.listCredentials();
Credential found = credentials.get(credentialId);
assertNotNull(found);
assertEquals(credential.getTypeName(), found.getTypeName());

//compare fields
assertEquals(credentialId, found.getId());
assertNotNull(found.getDisplayName());

//update the credential
String updateDescription = "updatedDescription";
credential.setDescription(updateDescription);
jenkinsServer.updateCredential(credentialId, credential, false);

//verify it is updated
credentials = jenkinsServer.listCredentials();
found = credentials.get(credentialId);
assertEquals(updateDescription, found.getDescription());

//delete the credential
jenkinsServer.deleteCredential(credentialId, false);
credentials = jenkinsServer.listCredentials();
assertFalse(credentials.containsKey(credentialId));
}
}
128 changes: 99 additions & 29 deletions jenkins-client/src/main/java/com/offbytwo/jenkins/JenkinsServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,31 @@

package com.offbytwo.jenkins;

import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;

import org.apache.http.HttpStatus;
import org.apache.http.client.HttpResponseException;
import org.apache.http.entity.ContentType;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.offbytwo.jenkins.client.JenkinsHttpClient;
import com.offbytwo.jenkins.client.util.EncodingUtils;
import com.offbytwo.jenkins.helper.JenkinsVersion;
import com.offbytwo.jenkins.model.Build;
import com.offbytwo.jenkins.model.Computer;
import com.offbytwo.jenkins.model.ComputerSet;
import com.offbytwo.jenkins.model.FolderJob;
import com.offbytwo.jenkins.model.Job;
import com.offbytwo.jenkins.model.JobConfiguration;
import com.offbytwo.jenkins.model.JobWithDetails;
import com.offbytwo.jenkins.model.LabelWithDetails;
import com.offbytwo.jenkins.model.MainView;
import com.offbytwo.jenkins.model.MavenJobWithDetails;
import com.offbytwo.jenkins.model.PluginManager;
import com.offbytwo.jenkins.model.Queue;
import com.offbytwo.jenkins.model.QueueItem;
import com.offbytwo.jenkins.model.QueueReference;
import com.offbytwo.jenkins.model.View;
import com.offbytwo.jenkins.model.*;
import com.offbytwo.jenkins.model.credentials.Credential;
import com.offbytwo.jenkins.model.credentials.CredentialManager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpResponseException;
import org.apache.http.entity.ContentType;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.net.URI;
import java.rmi.server.ExportException;
import java.util.List;
import java.util.Map;

/**
* The main starting point for interacting with a Jenkins server.
Expand All @@ -51,6 +40,8 @@ public class JenkinsServer {

private final JenkinsHttpClient client;

private CredentialManager credentialManager;

/**
* Create a new Jenkins server reference given only the server address
*
Expand Down Expand Up @@ -917,4 +908,83 @@ private String toViewBaseUrl(FolderJob folder, String name) {
return toBaseUrl(folder) + "view/" + EncodingUtils.encode(name);
}

/**
* List the credentials from the Jenkins server.
* @return a hash map of the credentials. The key is the id of each credential.
* @throws IOException
*/
public Map<String, Credential> listCredentials() throws IOException {
return this.getCredentialManager().listCredentials();
}

/**
* Create the given credential
* @param credential a credential instance
* @param crumbFlag
* @throws IOException
*/
public void createCredential(Credential credential, boolean crumbFlag) throws IOException {
this.getCredentialManager().createCredential(credential, crumbFlag);
}

/**
* Update an existing credential
* @param credentialId the id of the credential
* @param credential the updated credential instance
* @param crumbFlag
* @throws IOException
*/
public void updateCredential(String credentialId, Credential credential, boolean crumbFlag) throws IOException {
this.getCredentialManager().updateCredential(credentialId, credential, crumbFlag);
}

/**
* Delete an existing credential
* @param credentialId the id of the credential to delete
* @param crumbFlag
* @throws IOException
*/
public void deleteCredential(String credentialId, boolean crumbFlag) throws IOException {
this.getCredentialManager().deleteCredential(credentialId, crumbFlag);
}

/**
* Return the credentialManager instance. Will initialise it if it's never used before.
* @return the credentialManager instance
* @throws IOException
*/
private CredentialManager getCredentialManager() throws IOException {
if (this.credentialManager == null) {
Plugin credentialPlugin = findPluginWithName("credentials");
if (credentialPlugin == null) {
throw new ExportException("credential plugin is not installed");
}
String version = credentialPlugin.getVersion();
this.credentialManager = new CredentialManager(version, this.client);
}
return this.credentialManager;
}

/**
* Find a plugin that matches the given short name
* @param pluginShortName the short name of the plugin to find
* @return the pluin object that is found. Can be null if no match found.
* @throws IOException
*/
public Plugin findPluginWithName(final String pluginShortName) throws IOException {
List<Plugin> plugins = this.getPluginManager().getPlugins();
Object foundPlugin = CollectionUtils.find(plugins, new Predicate() {
@Override
public boolean evaluate(Object o) {
Plugin p = (Plugin) o;
if (p.getShortName().equalsIgnoreCase(pluginShortName)) {
return true;
} else {
return false;
}
}
});

return foundPlugin == null ? null : (Plugin) foundPlugin;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,58 @@ public void post_form(String path, Map<String, String> data, boolean crumbFlag)
}
}

/**
* Perform a POST request using form url encoding.
*
* This method was added for the purposes of creating credentials, but may be
* useful for other API calls as well.
*
* Unlike post and post_xml, the path is *not* modified by adding
* "/api/json". Additionally, the params in data are provided as both
* request parameters including a json parameter, *and* in the
* JSON-formatted StringEntity, because this is what the folder creation
* call required. It is unclear if any other jenkins APIs operate in this
* fashion.
*
* @param path path to request, can be relative or absolute
* @param data data to post
* @param crumbFlag true / false.
* @throws IOException in case of an error.
*/
public void post_form_json(String path, Map<String, Object> data, boolean crumbFlag) throws IOException {
HttpPost request;
if (data != null) {
// https://gist.github.com/stuart-warren/7786892 was slightly
// helpful here
List<String> queryParams = Lists.newArrayList();
queryParams.add("json=" + EncodingUtils.encodeParam(JSONObject.fromObject(data).toString()));
String value = mapper.writeValueAsString(data);
StringEntity stringEntity = new StringEntity(value, ContentType.APPLICATION_FORM_URLENCODED);
request = new HttpPost(noapi(path) + StringUtils.join(queryParams, "&"));
request.setEntity(stringEntity);
} else {
request = new HttpPost(noapi(path));
}

if (crumbFlag == true) {
Crumb crumb = get("/crumbIssuer", Crumb.class);
if (crumb != null) {
request.addHeader(new BasicHeader(crumb.getCrumbRequestField(), crumb.getCrumb()));
}
}

HttpResponse response = client.execute(request, localContext);
getJenkinsVersionFromHeader(response);

try {
httpResponseValidator.validateResponse(response);
} finally {
EntityUtils.consume(response.getEntity());
releaseConnection(request);
}
}


/**
* Perform a POST request of XML (instead of using json mapper) and return a
* string rendering of the response entity.
Expand Down
Loading