Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check job/folder existed and creating a folder #365

Closed
wants to merge 5 commits into from
Closed
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
2 changes: 1 addition & 1 deletion src/main/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG jenkins_tag=2.303.3-lts-jdk11
ARG jenkins_tag=2.414.3-lts-jdk17

FROM jenkins/jenkins:$jenkins_tag

Expand Down
25 changes: 25 additions & 0 deletions src/main/java/com/cdancy/jenkins/rest/JenkinsUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,18 @@
import static com.cdancy.jenkins.rest.JenkinsConstants.API_TOKEN_ENVIRONMENT_VARIABLE;
import static com.cdancy.jenkins.rest.JenkinsConstants.API_TOKEN_SYSTEM_PROPERTY;

import com.google.common.base.Charsets;
import com.google.common.base.Throwables;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.io.CharStreams;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
Expand All @@ -47,6 +51,7 @@
import java.util.Objects;
import java.util.Properties;

import org.jclouds.http.HttpResponse;
import org.jclouds.javax.annotation.Nullable;

/**
Expand All @@ -70,6 +75,26 @@ public static <T> List<T> nullToEmpty(final Iterable<? extends T> input) {
return input == null ? ImmutableList.of() : ImmutableList.copyOf(input);
}

/**
* Retrieves the text content from an HttpResponse object.
*
* This method extracts the payload from the HttpResponse, converts the InputStream to a String using UTF-8 encoding,
* and returns the result. In case of any exception during the process, it returns null.
*
* @param response the HttpResponse object containing the payload to be read
* @return the text content of the HttpResponse payload as a String, or null if an error occurs
*/
public static String getTextOutput(HttpResponse response) {
try (InputStream is = response.getPayload().openStream()) {
return CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8));
} catch (Exception e) {
// ignore
}
// ignore

return null;
}

/**
* Convert passed Map into an ImmutableMap.
*
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/com/cdancy/jenkins/rest/domain/job/Folder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.cdancy.jenkins.rest.domain.job;

/**
* Author: [email protected]
* Date:2024/9/11
* Time:15:52
*/

public class Folder {

private String name;
private String mode;
private Folder(){}

public Folder(String folderName){
this.name = folderName;
this.mode = "com.cloudbees.hudson.plugins.folder.Folder";
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getMode() {
return mode;
}

}
31 changes: 31 additions & 0 deletions src/main/java/com/cdancy/jenkins/rest/domain/job/JobExisted.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.cdancy.jenkins.rest.domain.job;

import com.google.auto.value.AutoValue;
import org.jclouds.json.SerializedNames;

/**
* Author: [email protected]
* Date:2024/9/11
* Time:12:45
*/

@AutoValue
public abstract class JobExisted {

public abstract String msg();
public abstract boolean existed();

JobExisted(){}

public static JobExisted create(String msg){
boolean existed = false;
if(msg!=null&&msg.contains("error")){
msg = msg.replace("<div class=\"error\">","").replace("</div>","");
existed = true;
}else {
msg = "";
}
return new AutoValue_JobExisted(msg,existed);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.cdancy.jenkins.rest.exception;

/**
* Author: [email protected]
* Date:2024/9/11
* Time:16:37
*/

public class JobCreateFailException extends RuntimeException{
private static final long serialVersionUID = 1L;

public JobCreateFailException(final String message) {
super(message);
}
}
42 changes: 27 additions & 15 deletions src/main/java/com/cdancy/jenkins/rest/features/JobsApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,21 @@
package com.cdancy.jenkins.rest.features;

import java.io.InputStream;

import com.cdancy.jenkins.rest.exception.JobCreateFailException;
import com.google.gson.JsonObject;
import java.util.List;
import java.util.Map;

import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

import com.cdancy.jenkins.rest.domain.job.*;
import com.cdancy.jenkins.rest.parsers.*;
import org.jclouds.Fallbacks;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.*;

import com.cdancy.jenkins.rest.binders.BindMapToForm;
import com.cdancy.jenkins.rest.domain.common.IntegerResponse;
Expand Down Expand Up @@ -89,6 +78,16 @@ InputStream artifact(@Nullable @PathParam("optionalFolderPath") @ParamParser(Opt
@PathParam("number") int buildNumber,
@PathParam("relativeArtifactPath") String relativeArtifactPath);


@Named("jobs:check-job-name")
@Path("{optionalFolderPath}checkJobName")
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
@Consumes(MediaType.APPLICATION_XHTML_XML)
@ResponseParser(JobExistedParser.class)
@GET
JobExisted checkJobName(@Nullable @PathParam("optionalFolderPath") @ParamParser(OptionalFolderPathParser.class) String optionalFolderPath,
@QueryParam("value") String jobName);

@Named("jobs:create")
@Path("{optionalFolderPath}createItem")
@Fallback(JenkinsFallbacks.RequestStatusOnError.class)
Expand All @@ -101,6 +100,19 @@ RequestStatus create(@Nullable @PathParam("optionalFolderPath") @ParamParser(Opt
@QueryParam("name") String jobName,
@PayloadParam(value = "configXML") String configXML);




@Named("jobs:create-folder")
@Path("{optionalFolderPath}createItem")
@Fallback(JenkinsFallbacks.RequestStatusOnError.class)
@ResponseParser(RequestStatusParser.class)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@QueryParams(keys = "mode", values = "com.cloudbees.hudson.plugins.folder.Folder")
@POST
RequestStatus createFolder(@Nullable @PathParam("optionalFolderPath") @ParamParser(OptionalFolderPathParser.class) String optionalFolderPath,
@QueryParam("name") String name);

@Named("jobs:get-config")
@Path("{optionalFolderPath}job/{name}/config.xml")
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public Integer apply(HttpResponse response) {
public String getTextOutput(HttpResponse response) {
InputStream is = null;
try {

is = response.getPayload().openStream();
return CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8)).trim();
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.cdancy.jenkins.rest.parsers;

import com.cdancy.jenkins.rest.domain.job.JobExisted;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jclouds.http.HttpResponse;
import com.google.common.base.Function;
import javax.inject.Singleton;

import static com.cdancy.jenkins.rest.JenkinsUtils.getTextOutput;

/**
* Author: [email protected]
* Date:2024/9/11
* Time:15:34
*/


@Singleton
public class JobExistedParser implements Function<HttpResponse, JobExisted> {
@Override
public @Nullable JobExisted apply(@Nullable HttpResponse httpResponse) {
return JobExisted.create(getTextOutput(httpResponse));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import com.google.common.base.Function;
import com.google.common.io.CharStreams;

import static com.cdancy.jenkins.rest.JenkinsUtils.getTextOutput;

/**
* Created by dancc on 3/11/16.
*/
Expand All @@ -43,16 +45,7 @@ public ProgressiveText apply(HttpResponse response) {
return ProgressiveText.create(text, size, hasMoreData);
}

public String getTextOutput(HttpResponse response) {
try (InputStream is = response.getPayload().openStream()) {
return CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8));
} catch (Exception e) {
// ignore
}
// ignore

return null;
}

public int getTextSize(HttpResponse response) {
String textSize = response.getFirstHeaderOrNull("X-Text-Size");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ public void testCreateJob() {
assertTrue(success.value());
}

@Test
public void testCreateFolder(){
RequestStatus success = api().createFolder(null,"DevTestFolder");
assertTrue(success.value());
}

// The next 3 tests must run one after the other as they use the same Job
@Test
public void testStopFreeStyleBuild() throws InterruptedException {
Expand Down Expand Up @@ -192,6 +198,20 @@ public void testGetJobInfo() {
assertTrue(output.builds().isEmpty());
}

@Test(dependsOnMethods = "testCreateJob")
public void testCheckJobNameExisted() {
JobExisted output = api().checkJobName(null,"DevTest");
assertNotNull(output);
assertTrue(output.existed());
}

@Test(dependsOnMethods = "testCreateJob")
public void testCheckJobNameNotExisted() {
JobExisted output = api().checkJobName(null,"DevTest1");
assertNotNull(output);
assertFalse(output.existed());
}

@Test(dependsOnMethods = "testGetJobInfo")
public void testLastBuildNumberOnJobWithNoBuilds() {
Integer output = api().lastBuildNumber(null, "DevTest");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import javax.ws.rs.core.MediaType;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -115,9 +116,52 @@ public void testGetJobInfoNotFound() throws Exception {
}
}

public void testGetBuildInfo() throws Exception {
public void testCheckJobNameExisted() throws Exception {
MockWebServer server = mockWebServer();
String body = payloadFromResource("/checkJobNameExisted.txt");
server.enqueue(new MockResponse().setBody(body).setResponseCode(200));
JenkinsApi jenkinsApi = api(server.url("/").url());
JobsApi api = jenkinsApi.jobsApi();
try {
JobExisted output = api.checkJobName(null,"DevTest");
assertTrue(output.existed());
} finally {
jenkinsApi.close();
server.shutdown();
}
}

public void testCheckJobNameNotExisted() throws Exception {
MockWebServer server = mockWebServer();
String body = payloadFromResource("/checkJobNameNotExisted.txt");
server.enqueue(new MockResponse().setBody(body).setResponseCode(200));
JenkinsApi jenkinsApi = api(server.url("/").url());
JobsApi api = jenkinsApi.jobsApi();
try {
JobExisted output = api.checkJobName(null,"DevTest1");
assertFalse(output.existed());
} finally {
jenkinsApi.close();
server.shutdown();
}
}

public void testCheckJobNameNotFound() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
JenkinsApi jenkinsApi = api(server.url("/").url());
JobsApi api = jenkinsApi.jobsApi();
try {
JobExisted output = api.checkJobName(null,"DevTest1");
assertNull(output);
} finally {
jenkinsApi.close();
server.shutdown();
}
}

public void testGetBuildInfo() throws Exception {
MockWebServer server = mockWebServer();
String body = payloadFromResource("/build-info.json");
server.enqueue(new MockResponse().setBody(body).setResponseCode(200));
JenkinsApi jenkinsApi = api(server.url("/").url());
Expand Down Expand Up @@ -174,6 +218,21 @@ public void testCreateJob() throws Exception {
server.shutdown();
}
}
public void testCreateFolder() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(200));
JenkinsApi jenkinsApi = api(server.url("/").url());
JobsApi api = jenkinsApi.jobsApi();
try {
RequestStatus success = api.createFolder(null, "DevTestFolder");
assertNotNull(success);
assertTrue(success.value());
assertTrue(success.errors().isEmpty());
} finally {
jenkinsApi.close();
server.shutdown();
}
}

public void testCreateJobInFolder() throws Exception {
MockWebServer server = mockWebServer();
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/checkJobNameExisted.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="error">A job already exists with the name ‘DevTest’</div>
1 change: 1 addition & 0 deletions src/test/resources/checkJobNameNotExisted.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div/>
Loading