Java client is built on the top of Http interface and webClient for working with Jenkins REST API Support Java 17 and Java 21.
Client's need jenkins properties and can be built like so:
JenkinsProperties jenkinsProperties = JenkinsProperties.builder().url("http://localhost:8080")
.jenkinsAuthentication(JenkinsAuthentication.builder().authType(AuthenticationType.USERNAME_PASSWORD)
.credentials("admin:password").build()).build();
JenkinsClient jenkinsClient = JenkinsClient.create(jenkinsProperties);
SystemInfo systemInfo = client.api().systemApi().systemInfo();
assertTrue(systemInfo.getUrl().equals("http://localhost:8080/"));
If Disabling CSRF Protection in your jenkins
hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true
Config your properties like that:
JenkinsProperties jenkinsProperties = JenkinsProperties.builder().url("http://localhost:8080")
.jenkinsAuthentication(JenkinsAuthentication.builder().crumbEnabled(false).authType(AuthenticationType.USERNAME_PASSWORD)
.credentials("admin:password").build()).build();
JenkinsClient jenkinsClient = JenkinsClient.create(jenkinsProperties);
SystemInfo systemInfo = client.api().systemApi().systemInfo();
assertTrue(systemInfo.getUrl().equals("http://localhost:8080/"));
Example of override the webClient for bearerAuth (Add the JenkinsUriTemplateHandler from jar):
WebClient webClient = WebClient.builder().uriBuilderFactory(new JenkinsUriTemplateHandler("http://localhost:8080"))
.filter((request, next) -> next.exchange(ClientRequest
.from(request).header(HttpHeaders.AUTHORIZATION,"Bearer " + "token here").build())).build();
}).build();
JenkinsProperties jenkinsProperties = JenkinsProperties.builder().url("http://localhost:8080")
.jenkinsAuthentication(JenkinsAuthentication.builder().crumbEnabled(false).build()).build();
JenkinsClient jenkinsClient = JenkinsClient.create(jenkinsProperties, webClient);
We can also add some filter from jar for example:
WebClient webClient = WebClient.builder().uriBuilderFactory(new JenkinsUriTemplateHandler("http://localhost:8080"))
.filter(new ScrubNullFolderParam())
.filter((request, next) -> next.exchange(ClientRequest
.from(request).header(HttpHeaders.AUTHORIZATION,"Bearer " + "token here").build())).build();
}).build();
JenkinsProperties jenkinsProperties = JenkinsProperties.builder().url("http://localhost:8080")
.jenkinsAuthentication(JenkinsAuthentication.builder().crumbEnabled(false).build()).build();
JenkinsClient jenkinsClient = JenkinsClient.create(jenkinsProperties, webClient);
Can be found in maven like so:
<dependency>
<groupId>io.github.hillelmed</groupId>
<artifactId>jenkins-client-java</artifactId>
<version>X.Y.Z</version>
<classifier>sources|tests|javadoc|all</classifier> (Optional)
</dependency>
- javadocs can be found via github pages here
- the jenkins-client-java wiki
Client instances do NOT need to supply the endPoint or credentials as a part of instantiating the JenkinsClient object. Instead, one can supply them through system properties, environment variables, or a combination of the two. System properties will be searched first and if not found, will attempt to query the environment.
Setting the endpoint
can be done with any of the following (searched in order):
jenkins.rest.endpoint
jenkinsRestEndpoint
JENKINS_REST_ENDPOINT
When none is found, the endpoint is set to http://localhost:8080
.
Setting the credentials
can be done with any of the following (searched in order):
jenkins.rest.api.token
jenkinsRestApiToken
JENKINS_REST_API_TOKEN
jenkins.rest.credentials
jenkinsRestCredentials
JENKINS_REST_CREDENTIALS
When none is found, no authentication is used (anonymous).
jenkins-rest credentials can take 1 of 3 forms:
- Colon delimited username and api token: admin:apiToken
- use
JenkinsAuthentication.builder().apiToken("admin:apiToken")
- use
- Colon delimited username and password: admin:password
- use
JenkinsAuthentication.builder().credentials("admin:password")
- use
- Base64 encoded username followed by password YWRtaW46cGFzc3dvcmQ= or api token YWRtaW46YXBpVG9rZW4=
- use
JenkinsAuthentication.builder().credentials("YWRtaW46cGFzc3dvcmQ=")
- use
JenkinsAuthentication.builder().apiToken("YWRtaW46YXBpVG9rZW4=")
- use
JenkinsProperties jenkinsProperties = JenkinsProperties.builder().url("http://localhost:8080")
.jenkinsAuthentication(JenkinsAuthentication.builder().credentials("admin:password").build()).build();
JenkinsClient jenkinsClient = JenkinsClient.create(jenkinsProperties);
The Jenkins crumb is automatically requested when POSTing using the anonymous and the username:password authentication methods. It is not requested when you use the apiToken as it is not needed in this case. For more details, see
When something pops server-side Jenkins
will hand us back a list
of JenkinsError
objects. we're throwing an exception at runtime we attach this List of Error
objects
The throwing object is
Jenkins JenkinsAppException.java
to
most domain
objects. Thus, it is up to the user to check the handed back domain object to see if the attached List is empty, and if
not, iterate over the Error
objects to see if it's something
truly warranting an exception. List of Error
objects itself will always be non-null but in most cases empty (unless
something has failed).
An example on how one might proceed:
try {
SystemInfo systemInfo = client.api().systemApi().systemInfo();
} catch (JenkinsAppException e) {
for(Error error : e.errors()) {
if (error.message().matches(".*Service unavailable.*")) {
throw new RuntimeException(error.message());
}
}
}
The mock and live tests provide many examples that you can use in your own code.
- Http Interface - used as the backend for communicating with Jenkins REST API
- WebClient - used as the backend for communicating with Jenkins REST API
- Spring - used as the backend for communicating with Jenkins REST API
- Lombok - used to create immutable value types both to and from the jenkins program
Running mock tests can be done like so:
./gradlew clean build mockTest
Running integration tests require an existing jenkins instance which can be obtained with docker:
docker build -t jenkins-rest/jenkins src/main/docker
docker run -d --rm -p 8080:8080 --name jenkins-rest jenkins-rest/jenkins
./gradlew clean build integTest
If you use the provided docker instance, there is no other preparation necessary. If you wish to run integration tests against your own Jenkins server, the requirements are outlined in the next section.
- a running instance accessible on http://127.0.0.1:8080 (can be changed in the gradle.properties file)
- Jenkins security
- Authorization: Anyone can do anything (to be able to test the crumb with the anonymous account)
- an
admin
user (credentials used by the tests can be changed in the gradle.properties file) withADMIN
role ( required as the tests install plugins) - CSRF protection enabled. Not mandatory but recommended by the Jenkins documentation. The lib supports Jenkins instances with our without this protection (see #14)
- Plugins
- CloudBees Credentials: otherwise an http 500 error occurs when
accessing
to http://127.0.0.1:8080/job/test-folder/job/test-folder-1/
java.lang.NoClassDefFoundError: com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider
- CloudBees Folder plugin installed
- OWASP Markup Formatter configured to use
Safe HTML
- Configuration As Code plugin installed
- Pipeline plugin installed
- CloudBees Credentials: otherwise an http 500 error occurs when
accessing
to http://127.0.0.1:8080/job/test-folder/job/test-folder-1/
This project provides instructions to setup a pre-configured Docker container
- jenkins url and authentication method used by the tests are defined in the
gradle.properties
file - by default, tests use the
credentials
(username:password) authentication method but this can be changed to use the API Token. See thegradle.properties
file.
- the
integTest
gradle task sets various System Properties - if you don't want to use gradle as tests runner in your IDE, configure the tests with the same kind of System Properties