added node command to get master

This commit is contained in:
Adrian Cole 2012-04-24 23:21:14 -07:00
parent 9884d04c2e
commit 5ee2cf6748
12 changed files with 605 additions and 1 deletions

View File

@ -18,9 +18,21 @@
*/ */
package org.jclouds.jenkins.v1; package org.jclouds.jenkins.v1;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import org.jclouds.jenkins.v1.domain.Node;
import org.jclouds.jenkins.v1.features.ComputerAsyncClient; import org.jclouds.jenkins.v1.features.ComputerAsyncClient;
import org.jclouds.jenkins.v1.features.JobAsyncClient; import org.jclouds.jenkins.v1.features.JobAsyncClient;
import org.jclouds.jenkins.v1.filters.BasicAuthenticationUnlessAnonymous;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/** /**
* Provides asynchronous access to Jenkins via their REST API. * Provides asynchronous access to Jenkins via their REST API.
@ -30,8 +42,18 @@ import org.jclouds.rest.annotations.Delegate;
* @see <a href="https://wiki.jenkins-ci.org/display/JENKINS/Remote+access+API">api doc</a> * @see <a href="https://wiki.jenkins-ci.org/display/JENKINS/Remote+access+API">api doc</a>
* @author Adrian Cole * @author Adrian Cole
*/ */
@RequestFilters(BasicAuthenticationUnlessAnonymous.class)
public interface JenkinsAsyncClient { public interface JenkinsAsyncClient {
/**
* @see JenkinsClient#getMaster
*/
@GET
@Path("/api/json")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Node> getMaster();
/** /**
* Provides asynchronous access to Computer features. * Provides asynchronous access to Computer features.
*/ */

View File

@ -21,6 +21,7 @@ package org.jclouds.jenkins.v1;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.jenkins.v1.domain.Node;
import org.jclouds.jenkins.v1.features.ComputerClient; import org.jclouds.jenkins.v1.features.ComputerClient;
import org.jclouds.jenkins.v1.features.JobClient; import org.jclouds.jenkins.v1.features.JobClient;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
@ -35,6 +36,10 @@ import org.jclouds.rest.annotations.Delegate;
*/ */
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface JenkinsClient { public interface JenkinsClient {
/**
* @return the master computer
*/
Node getMaster();
/** /**
* Provides synchronous access to Computer features. * Provides synchronous access to Computer features.

View File

@ -0,0 +1,157 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.jenkins.v1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
* Minimal info about a Job
*
* @author Adrian Cole
*/
public class Job {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return builder().fromJob(this);
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
}
public static abstract class Builder<B extends Builder<B>> {
private String name;
private URI url;
private String color;
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
/**
* @see Job#getName()
*/
public B name(String name) {
this.name = name;
return self();
}
/**
* @see Job#getUrl()
*/
public B url(URI url) {
this.url = url;
return self();
}
/**
* @see Job#getColor()
*/
public B color(String color) {
this.color = color;
return self();
}
public Job build() {
return new Job(this);
}
protected B fromJob(Job in) {
return name(in.getName()).color(in.getColor()).url(in.getUrl());
}
}
private final String name;
private final String color;
private final URI url;
protected Job(Builder<?> builder) {
this.name = checkNotNull(builder.name, "name");
this.color = checkNotNull(builder.color, "color");
this.url = checkNotNull(builder.url, "url");
}
/**
* name of the job
*/
public String getName() {
return name;
}
/**
*
* color of the job
*/
public String getColor() {
return color;
}
/**
*
* url of the job
*/
public URI getUrl() {
return url;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Job that = Job.class.cast(o);
return equal(this.name, that.name) && equal(this.url, that.url)
&& equal(this.color, that.color);
}
public boolean clone(Object o) {
if (this == o)
return false;
if (o == null || getClass() != o.getClass())
return false;
Job that = Job.class.cast(o);
return equal(this.color, that.color);
}
@Override
public int hashCode() {
return Objects.hashCode(name, url, color);
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return Objects.toStringHelper("").add("name", name).add("url", url).add("color",
color);
}
}

View File

@ -0,0 +1,62 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.jenkins.v1.domain;
import com.google.common.base.Objects.ToStringHelper;
/**
*
* @author Adrian Cole
*/
public class JobDetails extends Job {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
@Override
public Builder<?> toBuilder() {
return builder().fromJobDetails(this);
}
public static class Builder<B extends Builder<B>> extends Job.Builder<B> {
@Override
public JobDetails build() {
return new JobDetails(this);
}
public B fromJobDetails(JobDetails in) {
return fromJob(in);
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
}
protected JobDetails(Builder<?> builder) {
super(builder);
}
@Override
public ToStringHelper string() {
return super.string(); // .add("field", field);
}
}

View File

@ -0,0 +1,147 @@
package org.jclouds.jenkins.v1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableSet;
import com.google.gson.annotations.SerializedName;
/**
* @author Adrian Cole
* @see <a
* href="http://ci.jruby.org/api/">api
* doc</a>
*/
public class Node implements Comparable<Node> {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromNodeMetadata(this);
}
public static class Builder {
protected String name;
protected String description;
protected Set<Job> jobs = ImmutableSet.of();
/**
* @see Node#getName()
*/
public Builder name(String name) {
this.name = checkNotNull(name, "name");
return this;
}
/**
* @see Node#getDescription()
*/
public Builder description(String description) {
this.description = description;
return this;
}
/**
* @see Node#getJobs()
*/
public Builder jobs(Job... jobs) {
return jobs(ImmutableSet.copyOf(checkNotNull(jobs, "jobs")));
}
/**
* @see Node#getJobs()
*/
public Builder jobs(Set<Job> jobs) {
this.jobs = ImmutableSet.copyOf(checkNotNull(jobs, "jobs"));
return this;
}
public Node build() {
return new Node(name, description, jobs);
}
public Builder fromNodeMetadata(Node from) {
return name(from.getName()).description(from.getDescription()).jobs(from.getJobs());
}
}
@SerializedName("nodeName")
protected final String name;
@SerializedName("nodeDescription")
protected final String description;
protected final Set<Job> jobs;
public Node(String name, String description, Set<Job> jobs) {
this.name = checkNotNull(name, "name");
this.description = description;
this.jobs = ImmutableSet.copyOf(checkNotNull(jobs, "jobs"));
}
/**
*
* @return the name of the node
*/
public String getName() {
return name;
}
/**
*
* @return the description of the node
*/
public String getDescription() {
return description;
}
/**
* @return the jobs on this node
*/
public Set<Job> getJobs() {
return jobs;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Node) {
final Node other = Node.class.cast(object);
return equal(getName(), other.getName()) && equal(getDescription(), other.getDescription())
&& equal(getJobs(), other.getJobs());
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(getName(), getDescription(), getJobs());
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return toStringHelper("").add("name", getName()).add("description", getDescription()).add("jobs", getJobs());
}
@Override
public int compareTo(Node that) {
if (that == null)
return 1;
if (this == that)
return 0;
return this.getName().compareTo(that.getName());
}
}

View File

@ -61,4 +61,5 @@ public interface ComputerAsyncClient {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Computer> get(@PathParam("displayName") String displayName); ListenableFuture<Computer> get(@PathParam("displayName") String displayName);
} }

View File

@ -45,4 +45,5 @@ public interface ComputerClient {
* @return computer or null if not found * @return computer or null if not found
*/ */
Computer get(String displayName); Computer get(String displayName);
} }

View File

@ -0,0 +1,58 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.jenkins.v1;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.jenkins.v1.internal.BaseJenkinsClientExpectTest;
import org.jclouds.jenkins.v1.parse.ParseNodeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "JenkinsClientExpectTest")
public class JenkinsClientExpectTest extends BaseJenkinsClientExpectTest {
public void testGetMasterWhenResponseIs2xx() {
HttpRequest getMaster = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/api/json"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build();
HttpResponse getMasterResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/master.json")).build();
JenkinsClient clientWhenMasterExists = requestSendsResponse(getMaster, getMasterResponse);
assertEquals(clientWhenMasterExists.getMaster().toString(),
new ParseNodeTest().expected().toString());
}
}

View File

@ -0,0 +1,41 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.jenkins.v1;
import static org.testng.Assert.assertNotNull;
import org.jclouds.jenkins.v1.domain.Node;
import org.jclouds.jenkins.v1.internal.BaseJenkinsClientLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "JenkinsClientLiveTest")
public class JenkinsClientLiveTest extends BaseJenkinsClientLiveTest {
public void testGetMaster(){
Node master = context.getApi().getMaster();
assertNotNull(master);
assertNotNull(master.getName());
assertNotNull(master.getJobs());
}
}

View File

@ -0,0 +1,55 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.jenkins.v1.parse;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.jenkins.v1.domain.Job;
import org.jclouds.jenkins.v1.domain.Node;
import org.jclouds.json.BaseItemParserTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseNodeTest")
public class ParseNodeTest extends BaseItemParserTest<Node> {
@Override
public String resource() {
return "/master.json";
}
@Override
@Consumes(MediaType.APPLICATION_JSON)
public Node expected() {
return Node.builder()
.name("")
.description("the master Jenkins node")
.jobs(Job.builder()
.name("ddd")
.url(URI.create("http://localhost:8080/job/ddd/"))
.color("grey").build())
.build();
}
}

View File

@ -0,0 +1,29 @@
{
"actions": [],
"description": "",
"displayName": "ddd",
"displayNameOrNull": null,
"name": "ddd",
"url": "http://localhost:8080/job/ddd/",
"buildable": true,
"builds": [],
"color": "grey",
"firstBuild": null,
"healthReport": [],
"inQueue": false,
"keepDependencies": false,
"lastBuild": null,
"lastCompletedBuild": null,
"lastFailedBuild": null,
"lastStableBuild": null,
"lastSuccessfulBuild": null,
"lastUnstableBuild": null,
"lastUnsuccessfulBuild": null,
"nextBuildNumber": 1,
"property": [],
"queueItem": null,
"concurrentBuild": false,
"downstreamProjects": [],
"scm": {},
"upstreamProjects": []
}

View File

@ -0,0 +1,26 @@
{
"assignedLabels": [{}],
"mode": "NORMAL",
"nodeDescription": "the master Jenkins node",
"nodeName": "",
"numExecutors": 2,
"description": null,
"jobs": [{
"name": "ddd",
"url": "http://localhost:8080/job/ddd/",
"color": "grey"
}],
"overallLoad": {},
"primaryView": {
"name": "All",
"url": "http://localhost:8080/"
},
"quietingDown": false,
"slaveAgentPort": 0,
"useCrumbs": false,
"useSecurity": false,
"views": [{
"name": "All",
"url": "http://localhost:8080/"
}]
}