Skip to content

Commit 77ee9f3

Browse files
authored
Merge pull request #35 from tlmiller/SCRUM-3593
Work allows rdap-conformance to be used from within Docker.
2 parents 7622733 + 24910b9 commit 77ee9f3

27 files changed

+286
-24
lines changed

.travis.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
11
language: java
2+
jdk:
3+
- oraclejdk8
4+
- openjdk8
5+
6+
dist: trusty
7+
sudo: required
8+
9+
services:
10+
- docker
11+
12+
deploy:
13+
provider: script
14+
script: ./scripts/docker-deploy.sh
15+
on:
16+
branch: master
17+
jdk: openjdk8

Dockerfile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
FROM openjdk:8-jdk
3+
4+
ENV MAVEN_VERSION=3.2.5 \
5+
M2_HOME=/m2
6+
7+
RUN cd /tmp && \
8+
wget http://www-eu.apache.org/dist/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz && \
9+
tar xf apache-maven-$MAVEN_VERSION-bin.tar.gz && \
10+
mv apache-maven-$MAVEN_VERSION $M2_HOME && \
11+
rm -f apache-maven-$MAVEN_VERSION-bin.tar.gz
12+
13+
COPY pom.xml /build/
14+
15+
COPY src/ /build/src/
16+
COPY repo/ /build/repo/
17+
RUN cd /build && \
18+
$M2_HOME/bin/mvn verify -DskipDocker && \
19+
mkdir /app && \
20+
cp target/*.jar /app && \
21+
cp target/docker-extras/entrypoint.sh /app/ && \
22+
chmod 0744 /app/entrypoint.sh && \
23+
cd / && \
24+
rm -rf /build ${M2_HOME}
25+
26+
WORKDIR /app
27+
RUN useradd -MrU conformance && \
28+
chown -R conformance /app
29+
30+
EXPOSE 8080
31+
USER conformance
32+
ENTRYPOINT ["/app/entrypoint.sh", "rdap-configuration.json"]

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,45 @@ For example:
133133
}
134134
}
135135

136+
Docker
137+
------
138+
139+
`rdap-conformance` can be executed as a Docker container. The
140+
container works by having a test configuration file mounted into the
141+
container's file system. The return code of the container can be used
142+
to determine test success or failure.
143+
144+
### Building the image
145+
146+
The following command can be used to build an image:
147+
148+
```
149+
docker build -t apnic/rdap-conformance .
150+
```
151+
152+
### Running the container
153+
154+
To run the Docker container:
155+
156+
```
157+
docker run -d -v "{configuration-path}:/app/rdap-configuration.json" \
158+
--name rdap-conformance apnic/rdap-conformance
159+
```
160+
161+
<aside class="notice">
162+
It's important to note that the configuration file must be mounted
163+
into the container as a file, not a directory.
164+
</aside>
165+
166+
### Accessing the return code of the container
167+
168+
The below command can be used to access the return code for the
169+
container:
170+
171+
```
172+
docker wait rdap-conformance
173+
```
174+
136175
License
137176
-------
138177

pom.xml

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<groupId>net.apnic.rdap</groupId>
77
<artifactId>rdap-conformance</artifactId>
88
<packaging>jar</packaging>
9-
<version>0.4-SNAPSHOT</version>
9+
<version>0.4</version>
1010
<name>rdap-conformance</name>
1111
<description>RDAP conformance</description>
1212
<inceptionYear>2014</inceptionYear>
@@ -42,6 +42,34 @@
4242
<target>1.5</target>
4343
</configuration>
4444
</plugin>
45+
46+
<plugin>
47+
<artifactId>maven-resources-plugin</artifactId>
48+
<configuration>
49+
<escapeString>\</escapeString>
50+
</configuration>
51+
<executions>
52+
<execution>
53+
<id>docker-extras</id>
54+
<phase>prepare-package</phase>
55+
<goals>
56+
<goal>copy-resources</goal>
57+
</goals>
58+
<configuration>
59+
<!-- NOTE: We CANNOT use target/docker as that's being used by the docker-maven-plugin -->
60+
<!-- Recursive copy is not a good thing! -->
61+
<outputDirectory>${project.build.directory}/docker-extras/</outputDirectory>
62+
<resources>
63+
<resource>
64+
<directory>src/main/docker/</directory>
65+
<filtering>true</filtering>
66+
</resource>
67+
</resources>
68+
</configuration>
69+
</execution>
70+
</executions>
71+
</plugin>
72+
4573
<plugin>
4674
<groupId>org.apache.maven.plugins</groupId>
4775
<artifactId>maven-shade-plugin</artifactId>

scripts/docker-deploy.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
VERSION=`cat pom.xml | grep "^ <version>.*</version>$" | awk -F'[><]' '{print $3}'`
4+
5+
echo "Deploying Docker image for $VERSION"
6+
7+
docker build -t apnic/rdap-conformance:$VERSION \
8+
-t apnic/rdap-conformance:latest .
9+
10+
docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD"
11+
docker push apnic/rdap-conformance:$VERSION
12+
docker push apnic/rdap-conformance:latest

src/main/docker/entrypoint.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
echo "Launching with arguments: $@"
4+
5+
exec java -jar @project.artifactId@[email protected]@[email protected]@ "$\@"

src/main/java/net/apnic/rdap/conformance/Application.java

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
* @version 0.4-SNAPSHOT
3737
*/
3838
public final class Application {
39+
private static final int EX_FAILURE = 21;
3940
private static final int EX_USAGE = 64;
4041
private static final int EX_NOINPUT = 66;
4142
private static final int EX_SOFTWARE = 70;
@@ -87,7 +88,7 @@ private static String getJarName() {
8788
return jarName;
8889
}
8990

90-
private static void addSearchTests(final List<Test> tests,
91+
private static void addSearchTests(final TestAggregate tests,
9192
final ObjectClass oc,
9293
final SearchTest st,
9394
final String prefix,
@@ -145,7 +146,7 @@ private static Result getDocRefProto(final String document,
145146
}
146147

147148
private static void addNonRdapTests(final Context c,
148-
final List<Test> tests) {
149+
final TestAggregate tests) {
149150
/* Relative URI in the HTTP request. */
150151
Result relative = new Result();
151152
relative.setTestName("common.bad-uri-relative");
@@ -184,7 +185,7 @@ private static void addNonRdapTests(final Context c,
184185
}
185186

186187
private static void addUnsupportedQueryTypeTests(final Specification s,
187-
final List<Test> tests) {
188+
final TestAggregate tests) {
188189
/* Previously, this required that the server return a 400 (Bad
189190
* Request) for unsupported queries, as per using-http [5.4].
190191
* However, rdap-query now states that for documented query
@@ -211,7 +212,7 @@ private static void addUnsupportedQueryTypeTests(final Specification s,
211212
}
212213

213214
private static void addIpTests(final Specification s,
214-
final List<Test> tests) {
215+
final TestAggregate tests) {
215216
ObjectClass ocIp = s.getObjectClass("ip");
216217
if ((ocIp == null) || !ocIp.isSupported()) {
217218
return;
@@ -259,7 +260,7 @@ private static void addIpTests(final Specification s,
259260
}
260261

261262
private static void addAutnumTests(final Specification s,
262-
final List<Test> tests) {
263+
final TestAggregate tests) {
263264
ObjectClass ocAn = s.getObjectClass("autnum");
264265
if ((ocAn == null) || !ocAn.isSupported()) {
265266
return;
@@ -296,7 +297,7 @@ private static void addAutnumTests(final Specification s,
296297
}
297298

298299
private static void addNameserverTests(final Specification s,
299-
final List<Test> tests)
300+
final TestAggregate tests)
300301
throws Exception {
301302
ObjectClass ocNs = s.getObjectClass("nameserver");
302303
if ((ocNs == null) || !ocNs.isSupported()) {
@@ -347,7 +348,7 @@ private static void addNameserverTests(final Specification s,
347348
}
348349

349350
private static void addEntityTests(final Specification s,
350-
final List<Test> tests)
351+
final TestAggregate tests)
351352
throws Exception {
352353
ObjectClass ocEn = s.getObjectClass("entity");
353354
if ((ocEn == null) || !ocEn.isSupported()) {
@@ -398,7 +399,7 @@ private static void addEntityTests(final Specification s,
398399
}
399400

400401
private static void addDomainTests(final Specification s,
401-
final List<Test> tests)
402+
final TestAggregate tests)
402403
throws Exception {
403404
ObjectClass ocDom = s.getObjectClass("domain");
404405
if ((ocDom == null) || !ocDom.isSupported()) {
@@ -520,26 +521,26 @@ public static void main(final String[] args) throws Exception {
520521
}
521522

522523
String path = args[0];
523-
Specification s = null;
524+
Specification spec = null;
524525
try {
525-
s = Specification.fromPath(path);
526+
spec = Specification.fromPath(path);
526527
} catch (Exception e) {
527528
System.err.println("Unable to load specification "
528529
+ "path (" + path + "): "
529530
+ e.toString());
530531
System.exit(EX_NOINPUT);
531532
}
532-
if (s == null) {
533+
if (spec == null) {
533534
System.err.println("Specification (" + path + ") is empty.");
534535
System.exit(EX_NOINPUT);
535536
}
536537

537538
RateLimiter rateLimiter =
538-
(s.getRequestsPerSecond() > 0)
539-
? RateLimiter.create(s.getRequestsPerSecond())
539+
(spec.getRequestsPerSecond() > 0)
540+
? RateLimiter.create(spec.getRequestsPerSecond())
540541
: null;
541542

542-
List<Test> tests = new ArrayList();
543+
TestAggregate tests = new TestAggregate();
543544

544545
/* For now, the non-RDAP-specific tests are disabled. These
545546
* are fairly niche, and in many cases can't easily be fixed
@@ -553,7 +554,7 @@ public static void main(final String[] args) throws Exception {
553554
* than not testing the responses at all, allow for the
554555
* supported content type to be set in the configuration, and
555556
* add a result at the beginning indicating this failure. */
556-
if (s.getAcceptContentType() != null) {
557+
if (spec.getAcceptContentType() != null) {
557558
Result ctres = new Result();
558559
ctres.setTestName("common.rdap-specific-content-type");
559560
ctres.setDocument("rfc7480");
@@ -563,12 +564,12 @@ public static void main(final String[] args) throws Exception {
563564
System.out.println(ctres.toString());
564565
}
565566

566-
addUnsupportedQueryTypeTests(s, tests);
567-
addIpTests(s, tests);
568-
addAutnumTests(s, tests);
569-
addNameserverTests(s, tests);
570-
addEntityTests(s, tests);
571-
addDomainTests(s, tests);
567+
addUnsupportedQueryTypeTests(spec, tests);
568+
addIpTests(spec, tests);
569+
addAutnumTests(spec, tests);
570+
addNameserverTests(spec, tests);
571+
addEntityTests(spec, tests);
572+
addDomainTests(spec, tests);
572573

573574
tests.add(new net.apnic.rdap.conformance.test.help.Standard());
574575
AtomicInteger testsRunning = new AtomicInteger(0);
@@ -578,7 +579,7 @@ public static void main(final String[] args) throws Exception {
578579
.availableProcessors());
579580
for (final Test t : tests) {
580581
final Context context =
581-
createContext(s, rateLimiter, executorService, testsRunning);
582+
createContext(spec, rateLimiter, executorService, testsRunning);
582583
context.submitTest(t);
583584
}
584585

@@ -598,7 +599,7 @@ public static void main(final String[] args) throws Exception {
598599
ctres
599600
);
600601
final Context context =
601-
createContext(s, rateLimiter, executorService, testsRunning);
602+
createContext(spec, rateLimiter, executorService, testsRunning);
602603
context.setContentType("application/json");
603604
context.submitTest(test);
604605

@@ -614,5 +615,9 @@ public static void main(final String[] args) throws Exception {
614615
}
615616

616617
executorService.shutdown();
618+
619+
if(tests.hasFailure()) {
620+
System.exit(EX_FAILURE);
621+
}
617622
}
618623
}

src/main/java/net/apnic/rdap/conformance/Context.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ public void onSuccess(final HttpResponse httpResponse) {
249249
testsRunning.getAndDecrement();
250250
}
251251
public void onFailure(final Throwable t) {
252+
System.out.println("**********");
252253
test.setError(t);
253254
test.run();
254255
synchronized (System.out) {

src/main/java/net/apnic/rdap/conformance/Test.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ public interface Test {
3434
*/
3535
HttpRequest getRequest();
3636

37+
/**
38+
* <p>isFailure.</p>
39+
*
40+
* @return boolean indiciator if the test succeeded or passed
41+
*/
42+
boolean hasFailed();
43+
3744
/**
3845
* <p>setResponse.</p>
3946
*
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package net.apnic.rdap.conformance;
2+
3+
import java.util.ArrayList;
4+
5+
/**
6+
* Container class for holding a list of Test objects.
7+
*
8+
* This container is a child of java.util.ArrayList<Test> and provides helper
9+
* methods on to the list of Test objects.
10+
*
11+
* Note: Class does not implement any java.util.ArrayList<Test> constructors.
12+
* These can be added as needed.
13+
*/
14+
public class TestAggregate
15+
extends ArrayList<Test>
16+
{
17+
/**
18+
* Indicates if the at least one test in this aggregate has failed.
19+
*
20+
* @return boolean if at least one test in the aggregate has failed.
21+
*/
22+
public boolean hasFailure()
23+
{
24+
for(Test test : this) {
25+
if(test.hasFailed()) {
26+
return true;
27+
}
28+
}
29+
return false;
30+
}
31+
}

0 commit comments

Comments
 (0)