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
39 changes: 39 additions & 0 deletions src/main/java/com/amihaiemil/docker/RtSwarm.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,15 @@

import java.io.IOException;
import java.net.URI;
import javax.json.Json;
import javax.json.JsonObject;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;

/**
* Swarm API.
Expand Down Expand Up @@ -61,4 +68,36 @@ final class RtSwarm implements Swarm {
public JsonObject inspect() throws IOException {
return new Inspection(this.client, this.baseUri.toString());
}

@Override
public String init(final String listenAddress) throws IOException {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@llorllale Why return String here and bellow? Isn't the response a Json object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return this.init(
Json.createObjectBuilder()
.add("ListenAddr", listenAddress)
.add("ForceNewCluster", false)
.build()
);
}

@Override
public String init(final JsonObject spec) throws IOException {
final HttpPost init = new HttpPost(this.baseUri.toString() + "/init");
try {
init.setEntity(
new StringEntity(
spec.toString(), ContentType.APPLICATION_JSON
)
);
final HttpResponse response = this.client.execute(init);
final int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_OK) {
return EntityUtils.toString(response.getEntity());
}
throw new UnexpectedResponseException(
init.getRequestLine().getUri(), status, HttpStatus.SC_OK
);
} finally {
init.releaseConnection();
}
}
}
20 changes: 19 additions & 1 deletion src/main/java/com/amihaiemil/docker/Swarm.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* @author George Aristy (george.aristy@gmail.com)
* @version $Id$
* @since 0.0.1
* @todo #3:30min Implement all of the Swarm operations. See
* @todo #70:30min Continue implementing all of the Swarm operations. See
* https://docs.docker.com/engine/api/v1.35/#tag/Swarm for reference and also
* the roadmap laid out here:
* https://github.com/amihaiemil/docker-java-api/issues/3#issuecomment-375821822
Expand All @@ -52,4 +52,22 @@ public interface Swarm {
* @throws IOException If something goes wrong.
*/
JsonObject inspect() throws IOException;

/**
* Initialize a new swarm.
* @param listenAddress Listen address used for inter-manager communication.
* This can either be in the form of '192.168.1.1:4567' or 'eth0:4567'
* where the port number is optional in both cases.
* @return The swarm's token.
* @throws IOException If something goes wrong.
*/
String init(String listenAddress) throws IOException;

/**
* Initialize a new swarm by providing a full specification.
* @param spec Full specification for the swarm.
* @return The swarm's token.
* @throws IOException If something goes wrong.
*/
String init(JsonObject spec) throws IOException;
}
73 changes: 73 additions & 0 deletions src/test/java/com/amihaiemil/docker/RtSwarmTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import com.amihaiemil.docker.mock.AssertRequest;
import com.amihaiemil.docker.mock.Condition;
import com.amihaiemil.docker.mock.PayloadOf;
import com.amihaiemil.docker.mock.Response;
import java.net.URI;
import org.apache.http.HttpStatus;
Expand Down Expand Up @@ -131,4 +132,76 @@ public void inspectThrowsErrorIfResponseIs503() throws Exception {
), URI.create("http://localhost")
).inspect();
}

/**
* The init request should have correct URI, method, and also its JSON
* payload should have at least the 'ListenAddr' and 'ForceNewCluster'
* properties.
* @throws Exception If an error occurs.
*/
@Test
public void initRequestWellformed() throws Exception {
final String listenAddress = "172.27.9.10";
new RtSwarm(
new AssertRequest(
new Response(HttpStatus.SC_OK, "sometoken123"),
new Condition(
"Request method must be POST.",
req -> "POST".equals(req.getRequestLine().getMethod())
),
new Condition(
"The 'ListenAddr' attribute is mandatory.",
req -> new PayloadOf(req).containsKey("ListenAddr")
),
new Condition(
"The 'ListenAddr' value must be the same as the one given.",
req -> listenAddress.equals(
new PayloadOf(req).getString("ListenAddr")
)
),
new Condition(
"The 'ForceNewCluster' attribute is mandatory.",
req -> new PayloadOf(req).containsKey("ForceNewCluster")
),
new Condition(
"The 'ForceNewCluster' attribute cannot be empty.",
req -> !new PayloadOf(req).isNull("ForceNewCluster")

)
),
URI.create("http://docker/swarm")
).init(listenAddress);
}

/**
* Must return the same token returned by Docker.
* @throws Exception If something goes wrong.
*/
@Test
public void initReturnsSwarmToken() throws Exception {
MatcherAssert.assertThat(
new RtSwarm(
new AssertRequest(
new Response(HttpStatus.SC_OK, "sometoken123")
),
URI.create("http://docker")
).init("123"),
Matchers.is("sometoken123")
);
}

/**
* Must throw {@link UnexpectedResponseException} if docker responds with
* a code different from 200.
* @throws Exception If an error occurs.
*/
@Test(expected = UnexpectedResponseException.class)
public void initUnexpectedErrorIfResponseIsNot200() throws Exception {
new RtSwarm(
new AssertRequest(
new Response(HttpStatus.SC_BAD_REQUEST, "")
),
URI.create("http://docker")
).init("123");
}
}