Skip to content

Commit

Permalink
feat(testing): Implement basic integration test (see #JENKINS-40673)
Browse files Browse the repository at this point in the history
Basic docker-based integration test infrastructure for RocketChat
  • Loading branch information
hypery2k committed Dec 26, 2016
1 parent 87f2d71 commit 01c249d
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 144 deletions.
70 changes: 69 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
<jackson.version>2.7.0</jackson.version>
<hamcrest.version>1.3</hamcrest.version>
<powermock.version>1.6.2</powermock.version>
<!-- testing config -->
<rocket.version>latest</rocket.version>
<rocket.port>4443</rocket.port>
<mongo.port>27017</mongo.port>
<docker-maven-plugin.version>2.11.19</docker-maven-plugin.version>
</properties>


Expand Down Expand Up @@ -50,6 +55,20 @@

<build>
<plugins>
<plugin>
<groupId>com.alexecollins.docker</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker-maven-plugin.version}</version>
<configuration>
<!-- (optional) remove images created by Dockerfile (default true) -->
<removeIntermediateImages>true</removeIntermediateImages>
<!-- (optional) do/do not cache images (default false), disable to
get the freshest images -->
<cache>true</cache>
<!-- (optional) only remove containers on clean, do not remove images -->
<cleanContainerOnly>false</cleanContainerOnly>
</configuration>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.2</version>
Expand All @@ -68,6 +87,54 @@
</plugins>
</build>

<profiles>
<profile>
<id>docker</id>
<properties>
<webdriver.base.url>http://localhost:41080/</webdriver.base.url>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<ldap.url>ldap://127.0.0.1:${rocket.port}</ldap.url>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>com.alexecollins.docker</groupId>
<artifactId>docker-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>com.kohlschutter.junixsocket</groupId>
<artifactId>junixsocket-common</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>com.kohlschutter.junixsocket</groupId>
<artifactId>junixsocket-native-common</artifactId>
<version>2.0.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>validate</goal>
<goal>clean</goal>
<goal>package</goal>
<goal>start</goal>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<dependencies>

Expand Down Expand Up @@ -219,7 +286,8 @@

<issueManagement>
<system>JIRA</system>
<url>https://issues.jenkins-ci.org/issues/?jql=project+%3D+JENKINS+AND+component+%3D+rocket-chat-notifier-plugin</url>
<url>https://issues.jenkins-ci.org/issues/?jql=project+%3D+JENKINS+AND+component+%3D+rocket-chat-notifier-plugin
</url>
</issueManagement>

<ciManagement>
Expand Down
1 change: 1 addition & 0 deletions src/main/docker/mongo/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM mongo:latest
7 changes: 7 additions & 0 deletions src/main/docker/mongo/conf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ports:
- ${mongo.port}
healthChecks:
pings:
- url: http://localhost:${mongo.port}/
timeout: 60000
tag: jenkins-plugin/${project.artifactId}-mongo:${project.version}
27 changes: 27 additions & 0 deletions src/main/docker/rocketchat/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM rocketchat/base:4

ENV RC_VERSION latest

MAINTAINER [email protected]

VOLUME /app/uploads

RUN set -x \
&& curl -SLf "https://rocket.chat/releases/${rocket.version}/download" -o rocket.chat.tgz \
&& curl -SLf "https://rocket.chat/releases/${rocket.version}/asc" -o rocket.chat.tgz.asc \
&& gpg --verify rocket.chat.tgz.asc \
&& tar -zxf rocket.chat.tgz -C /app \
&& rm rocket.chat.tgz rocket.chat.tgz.asc \
&& cd /app/bundle/programs/server \
&& npm install \
&& npm cache clear

USER rocketchat

WORKDIR /app/bundle

ADD run.sh /app/bundle

EXPOSE ${rocket.port}

CMD ["bash", "/app/bundle/run.sh"]
10 changes: 10 additions & 0 deletions src/main/docker/rocketchat/conf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ports:
- ${rocket.port}
# containers that this should be linked to, started before this one and stopped afterwards
links:
- mongo:mongo
healthChecks:
pings:
- url: http://localhost:${rocket.port}/
timeout: 60000
tag: jenkins-plugin/${project.artifactId}-rocket:${project.version}
15 changes: 15 additions & 0 deletions src/main/docker/rocketchat/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh
# needs a mongoinstance - defaults to container linking with alias 'mongo'

MONGO_HOST=$MONGO_PORT_${mongo.port}_TCP_ADDR":"${mongo.port}

export MONGO_URL=mongodb://${MONGO_HOST}/rocketchat
export HOME=/tmp
export PORT=${rocket.port}
export ROOT_URL=http://localhost:${rocket.port}
export Accounts_AvatarStorePath=/app/uploads
export ADMIN_USERNAME=admin
export ADMIN_PASS=supersecret
export [email protected]

node main.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import hudson.tasks.Publisher;
import hudson.util.FormValidation;
import jenkins.model.JenkinsLocationConfiguration;
import jenkins.plugins.rocketchatnotifier.rocket.RocketChatClient;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
package jenkins.plugins.rocketchatnotifier;


import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import jenkins.plugins.rocketchatnotifier.model.Message;
import jenkins.plugins.rocketchatnotifier.model.Room;
import jenkins.plugins.rocketchatnotifier.model.Rooms;
import org.json.JSONObject;
import jenkins.plugins.rocketchatnotifier.rocket.RocketChatClient;
import sun.security.validator.ValidatorException;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

/**
Expand Down Expand Up @@ -53,132 +40,3 @@ public boolean publish(String message) {
}


class RocketChatClient {
private final String serverUrl;
private final String user;
private final String password;
private String xAuthToken;
private String xUserId;
private ObjectMapper jacksonObjectMapper;
Map<String, Room> roomCache = new HashMap();
JSONObject lazyVersions;

public RocketChatClient(String serverUrl, String user, String password) {
this.serverUrl = serverUrl;
this.user = user;
this.password = password;
this.jacksonObjectMapper = new ObjectMapper();
this.jacksonObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}

public Set<Room> getPublicRooms() throws IOException {
Rooms rooms = (Rooms) this.authenticatedGet("publicRooms", Rooms.class);
HashSet ret = new HashSet();
this.roomCache.clear();
Room[] roomsArray = rooms.getRooms();
int numberOfRooms = roomsArray.length;

for (int i = 0; i < numberOfRooms; ++i) {
Room room = roomsArray[i];
ret.add(room);
this.roomCache.put(room.getName(), room);
}

return ret;
}

private <T> T authenticatedGet(String method, Class<T> reponseClass) throws IOException {
try {
HttpResponse e = Unirest.get(this.serverUrl + method).header("X-Auth-Token", this.xAuthToken).header("X-User-Id", this.xUserId).asString();
if (e.getStatus() == 401) {
this.login();
return this.authenticatedGet(method, reponseClass);
} else {
return this.jacksonObjectMapper.readValue((String) e.getBody(), reponseClass);
}
} catch (UnirestException var4) {
throw new IOException(var4);
}
}

private void authenticatedPost(String method, Object request) throws ValidatorException, IOException {
this.authenticatedPost(method, request, (Class) null);
}

private <T> T authenticatedPost(String method, Object request, Class<T> reponseClass) throws ValidatorException, IOException {
try {
HttpResponse e = Unirest.post(this.serverUrl + method).header("X-Auth-Token", this.xAuthToken).header("X-User-Id", this.xUserId).header("Content-Type", "application/json").body(this.jacksonObjectMapper.writeValueAsString(request)).asString();
if (e.getStatus() == 401) {
this.login();
return this.authenticatedPost(method, request, reponseClass);
} else {
return reponseClass == null ? null : this.jacksonObjectMapper.readValue((String) e.getBody(), reponseClass);
}
} catch (UnirestException var5) {
throw new IOException(var5);
}
}

void login() throws UnirestException {
HttpResponse asJson = Unirest.post(this.serverUrl + "login").field("user", this.user).field("password", this.password).asJson();
if (asJson.getStatus() == 401) {
throw new UnirestException("401 - Unauthorized");
} else {
JSONObject data = ((JsonNode) asJson.getBody()).getObject().getJSONObject("data");
this.xAuthToken = data.getString("authToken");
this.xUserId = data.getString("userId");
}
}

public void logout() throws IOException {
try {
Unirest.post(this.serverUrl + "logout").header("X-Auth-Token", this.xAuthToken).header("X-User-Id", this.xUserId).asJson();
} catch (UnirestException var2) {
throw new IOException(var2);
}
}

public String getApiVersion() throws IOException {
return this.getVersions().getString("api");
}

public String getRocketChatVersion() throws IOException {
return this.getVersions().getString("rocketchat");
}

private JSONObject getVersions() throws IOException {
if (this.lazyVersions == null) {
try {
this.lazyVersions = ((JsonNode) Unirest.get(this.serverUrl + "version").asJson().getBody()).getObject().getJSONObject("versions");
} catch (UnirestException var2) {
throw new IOException(var2);
}
}

return this.lazyVersions;
}

public void send(String roomName, String message) throws ValidatorException, IOException {
Room room = this.getRoom(roomName);
if (room == null) {
throw new IOException(String.format("unknown room : %s", new Object[]{roomName}));
} else {
this.send(room, message);
}
}

public void send(Room room, String message) throws ValidatorException, IOException {
this.authenticatedPost("rooms/" + room.get_id() + "/send", new Message(message));
}

public Room getRoom(String room) throws IOException {
Room ret = (Room) this.roomCache.get(room);
if (ret == null) {
this.getPublicRooms();
ret = (Room) this.roomCache.get(room);
}

return ret;
}
}

Loading

0 comments on commit 01c249d

Please sign in to comment.