diff --git a/README.md b/README.md index b8ad8a94af..12c7da09ec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Example Voting App ========= +Test 4 + Getting started --------------- diff --git a/e2e/.env b/e2e/.env new file mode 100644 index 0000000000..2b8eeabadd --- /dev/null +++ b/e2e/.env @@ -0,0 +1,3 @@ +VOTE_IMAGE=initcron/vote:master +WORKER_IMAGE=initcron/worker:master +RESULT_IMAGE=initcron/result:master diff --git a/e2e/docker-compose.test.yml b/e2e/docker-compose.yml similarity index 85% rename from e2e/docker-compose.test.yml rename to e2e/docker-compose.yml index 0df964e646..2715543309 100644 --- a/e2e/docker-compose.test.yml +++ b/e2e/docker-compose.yml @@ -2,17 +2,19 @@ version: '2' services: - sut: + e2e: build: ./tests/ depends_on: - vote - result - worker + - db + - redis networks: - front-tier vote: - build: ../vote/ + image: ${VOTE_IMAGE} ports: ["80"] depends_on: - redis @@ -22,7 +24,7 @@ services: - back-tier result: - build: . + image: ${RESULT_IMAGE} ports: ["80"] depends_on: - redis @@ -32,7 +34,7 @@ services: - back-tier worker: - build: ../worker/ + image: ${WORKER_IMAGE} depends_on: - redis - db @@ -47,8 +49,6 @@ services: db: image: postgres:9.4 - volumes: - - "db-data:/var/lib/postgresql/data" networks: - back-tier diff --git a/e2e/tests/tests.sh b/e2e/tests/tests.sh index 448159454b..4044cc63a7 100755 --- a/e2e/tests/tests.sh +++ b/e2e/tests/tests.sh @@ -1,13 +1,31 @@ -#!/bin/sh +#!/bin/bash while ! timeout 1 bash -c "echo > /dev/tcp/vote/80"; do sleep 1 done +current=`phantomjs render.js http://result | grep -i vote | cut -d ">" -f 4 | cut -d " " -f1` +next=`echo "$(($current + 1))"` + + echo -e "\n\n-----------------" + echo -e "Current Votes Count: $current" + echo -e "-----------------\n" + +echo -e " I: Submitting one more vote...\n" + curl -sS -X POST --data "vote=b" http://vote > /dev/null sleep 10 -if phantomjs render.js http://result | grep -q '1 vote'; then +new=`phantomjs render.js http://result | grep -i vote | cut -d ">" -f 4 | cut -d " " -f1` + + + echo -e "\n\n-----------------" + echo -e "New Votes Count: $new" + echo -e "-----------------\n" + +echo -e "I: Checking if votes tally......\n" + +if [ "$next" -eq "$new" ]; then echo -e "\\e[42m------------" echo -e "\\e[92mTests passed" echo -e "\\e[42m------------" diff --git a/result/Jenkinsfile b/result/Jenkinsfile new file mode 100644 index 0000000000..3d8c78a043 --- /dev/null +++ b/result/Jenkinsfile @@ -0,0 +1,77 @@ +pipeline { + + agent none + + triggers { pollSCM('H/2 * * * *') } + + stages { + stage('Build') { + when { + changeset "**/result/**" + } + agent { + docker { + image 'node:8.9-alpine' + } + } + steps { + echo 'Building..' + dir('result'){ + sh 'npm install' + } + } + } + + stage('Test') { + when { + changeset "**/result/**" + } + agent { + docker { + image 'node:8.9-alpine' + } + } + steps { + echo 'Testing..' + dir('result'){ + sh 'npm install' + sh 'npm test' + } + } + } + + stage('Sonarqube') { + when { + changeset "**/result/**" + branch 'master' + } + agent any + environment{ + sonarpath = tool 'SonarScanner' + } + steps { + echo 'Running Sonarqube Analysis..' + withSonarQubeEnv('sonar') { + sh "${sonarpath}/bin/sonar-scanner -Dproject.settings=result/sonar-project.properties" + } + } + } + + stage('Package with Docker') { + when { + changeset "**/result/**" + } + agent any + steps { + echo 'Building and Publishing Docker Image' + script { + docker.withRegistry('https://index.docker.io/v1/', 'dockerhub') { + def customImage = docker.build("initcron/result:${env.BRANCH_NAME}-v${env.BUILD_ID}", "./result") + customImage.push("${env.BRANCH_NAME}") + customImage.push() + } + } + } + } + } +} diff --git a/result/package.json b/result/package.json index f7863e1a1d..f0ac5fb3a6 100644 --- a/result/package.json +++ b/result/package.json @@ -1,10 +1,10 @@ { "name": "result", - "version": "1.0.0", + "version": "1.1.0", "description": "", "main": "server.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node_modules/.bin/mocha" }, "author": "", "license": "MIT", @@ -16,5 +16,9 @@ "async": "^1.5.0", "pg": "^4.4.3", "socket.io": "^1.3.7" + }, + "devDependencies": { + "chai": "^4.0.2", + "mocha": "^3.4.2" } } diff --git a/result/test/mock.test.js b/result/test/mock.test.js new file mode 100644 index 0000000000..f99dfdae97 --- /dev/null +++ b/result/test/mock.test.js @@ -0,0 +1,29 @@ +const expect = require('chai').expect; + +describe('mock test 1', () => { + it('unit test 1', () => { + expect(true).to.be.true; + }); +}); + + +describe('mock test 2', () => { + it('unit test 2', () => { + expect(true).to.be.true; + }); +}); + +describe('mock test 3', () => { + it('unit test 3', () => { + expect(true).to.be.true; + }); +}); + + +describe('mock test 4', () => { + it('unit test 4', () => { + expect(true).to.be.true; + }); +}); + + diff --git a/vote/Jenkinsfile b/vote/Jenkinsfile new file mode 100644 index 0000000000..1036c923bf --- /dev/null +++ b/vote/Jenkinsfile @@ -0,0 +1,80 @@ +pipeline { + + agent none + + triggers { pollSCM('H/2 * * * *') } + + stages { + + stage('Build') { + when { + changeset "**/vote/**" + } + agent { + docker { + image 'python:2.7-alpine' + args '--user root' + } + } + steps { + echo 'Building..' + dir('vote'){ + sh 'pip install -r requirements.txt' + } + } + } + + stage('Test') { + when { + changeset "**/vote/**" + } + agent { + docker { + image 'python:2.7-alpine' + args '--user root' + } + } + steps { + echo 'Testing..' + dir('vote'){ + sh 'pip install -r requirements.txt' + sh 'nosetests -v' + } + } + } + + stage('Sonarqube') { + when { + changeset "**/vote/**" + branch 'master' + } + agent any + environment{ + sonarpath = tool 'SonarScanner' + } + steps { + echo 'Running Sonarqube Analysis..' + withSonarQubeEnv('sonar') { + sh "${sonarpath}/bin/sonar-scanner -Dproject.settings=vote/sonar-project.properties" + } + } + } + + stage('Package with Docker') { + when { + changeset "**/vote/**" + } + agent any + steps { + echo 'Building and Publishing Docker Image' + script { + docker.withRegistry('https://index.docker.io/v1/', 'dockerhub') { + def customImage = docker.build("initcron/vote:${env.BRANCH_NAME}-v${env.BUILD_ID}", "./vote") + customImage.push("${env.BRANCH_NAME}") + customImage.push() + } + } + } + } + } +} diff --git a/vote/integration/Dockerfile b/vote/integration/Dockerfile new file mode 100644 index 0000000000..c44c018e5f --- /dev/null +++ b/vote/integration/Dockerfile @@ -0,0 +1,5 @@ +FROM alpine:3.9.4 +WORKDIR /test +COPY . . +RUN apk add curl +CMD sh diff --git a/vote/integration/docker-compose.yaml b/vote/integration/docker-compose.yaml new file mode 100644 index 0000000000..dc73e9eb85 --- /dev/null +++ b/vote/integration/docker-compose.yaml @@ -0,0 +1,26 @@ +version: "3" + +services: + + integration: + build: ./ + networks: + - integration + + vote: + build: ../ + ports: ["80"] + depends_on: + - redis + networks: + - integration + + redis: + image: redis:alpine + ports: ["6379"] + networks: + - integration + +networks: + integration: + diff --git a/vote/integration/test.sh b/vote/integration/test.sh new file mode 100644 index 0000000000..0d0043aff7 --- /dev/null +++ b/vote/integration/test.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +echo "I: Checking if frontend vote app is available..." + +curl http://vote > /dev/null 2>&1 + +if [ $? -eq 0 ] +then + echo "---------------------------------------" + echo "Vote app is available....proceeding" + echo "---------------------------------------" +else + echo "---------------------------------------" + echo "Vote app is not avilable....aborting" + echo "---------------------------------------" + exit 2 +fi + + +echo "I: Launching integration test..." + +# submit a vote. Will return an error if it fails to submit or store vote in redis +# Fail integration test if it returns exit code 0 (error state) + +curl -sS -X POST --data "vote=b" http://vote | grep -i erro + +if [ $? -eq 0 ] +then + # error, failed + exit 1 +else + # passed + exit 0 +fi + + diff --git a/vote/integration_test.sh b/vote/integration_test.sh new file mode 100644 index 0000000000..956dcdea8a --- /dev/null +++ b/vote/integration_test.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +cd integration + +echo "I: Creating environment to run integration tests..." + +docker-compose build +docker-compose up -d + + +echo "I: Launching Integration Test ..." + +docker-compose run --rm integration /test/test.sh + +if [ $? -eq 0 ] +then + echo "---------------------------------------" + echo "INTEGRATION TESTS PASSED....." + echo "---------------------------------------" + docker-compose down + cd .. + exit 0 +else + echo "---------------------------------------" + echo "INTEGRATION TESTS FAILED....." + echo "---------------------------------------" + docker-compose down + cd .. + exit 1 +fi diff --git a/vote/requirements.txt b/vote/requirements.txt index 430bfdcd89..d3cbfb8f41 100644 --- a/vote/requirements.txt +++ b/vote/requirements.txt @@ -1,3 +1,4 @@ Flask Redis gunicorn +nose diff --git a/worker/Dockerfile b/worker/Dockerfile new file mode 100644 index 0000000000..9ab8d5d971 --- /dev/null +++ b/worker/Dockerfile @@ -0,0 +1,11 @@ +FROM schoolofdevops/maven + +WORKDIR /app + +COPY . . + +RUN mvn package && \ + mv target/worker-jar-with-dependencies.jar /run/worker.jar && \ + rm -rf /app/* + +CMD java -jar /run/worker.jar diff --git a/worker/Jenkinsfile b/worker/Jenkinsfile new file mode 100644 index 0000000000..4a263f5b73 --- /dev/null +++ b/worker/Jenkinsfile @@ -0,0 +1,32 @@ +pipeline { + agent any + + triggers { pollSCM('H/2 * * * *') } + + tools { + maven 'Maven 3.6.1' + } + + stages { + stage('Build') { + steps { + echo 'Building..' + sh 'mvn -f worker/pom.xml compile' + } + } + + stage('Test') { + steps { + echo 'Testing..' + sh 'mvn -f worker/pom.xml test' + } + } + stage('Package') { + steps { + echo 'Packaging....' + sh 'mvn -f worker/pom.xml package -DskipTests' + archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true + } + } + } +} diff --git a/worker/Jenkinsfile.docker b/worker/Jenkinsfile.docker new file mode 100644 index 0000000000..9c57ec454f --- /dev/null +++ b/worker/Jenkinsfile.docker @@ -0,0 +1,96 @@ +pipeline { + + agent any + + + stages { + stage('Build') { + when { + changeset "**/worker/**" + } + agent { + docker { + image 'maven:3-alpine' + args '-v $HOME/.m2:/root/.m2' + } + } + steps { + echo 'Building..' + dir('worker'){ + sh 'mvn compile' + } + } + } + + stage('Test') { + when { + changeset "**/worker/**" + } + agent { + docker { + image 'maven:3-alpine' + args '-v $HOME/.m2:/root/.m2' + } + } + steps { + echo 'Testing..' + dir('worker'){ + sh 'mvn test' + } + } + } + + stage('Sonarqube') { + when { + changeset "**/worker/**" + branch 'master' + } + agent any + environment{ + sonarpath = tool 'SonarScanner' + } + steps { + echo 'Running Sonarqube Analysis..' + withSonarQubeEnv('sonar') { + sh "${sonarpath}/bin/sonar-scanner -Dproject.settings=worker/sonar-project.properties" + } + } + } + + stage('Package') { + when { + changeset "**/worker/**" + } + agent { + docker { + image 'maven:3-alpine' + args '-v $HOME/.m2:/root/.m2' + } + } + steps { + echo 'Packaging....' + dir('worker'){ + sh 'mvn package -DskipTests' + archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true + } + } + } + + stage('Package with Docker') { + when { + changeset "**/worker/**" + } + agent any + steps { + echo 'Building and Publishing Docker Image' + script { + docker.withRegistry('https://index.docker.io/v1/', 'dockerhub') { + def customImage = docker.build("initcron/worker:${env.BRANCH_NAME}-v${env.BUILD_ID}", "./worker") + customImage.push("${env.BRANCH_NAME}") + customImage.push() + } + } + } + } + } +} diff --git a/worker/README.md b/worker/README.md new file mode 100644 index 0000000000..7358b615fa --- /dev/null +++ b/worker/README.md @@ -0,0 +1,6 @@ + +### Build Status + +[![Build Status](http://128.199.243.222:8080/buildStatus/icon?job=instavote%2Fworker-build&subject=Build)](http://128.199.243.222:8080/job/instavote/job/worker-build/) + +[![Unit Test Status](http://128.199.243.222:8080/buildStatus/icon?job=instavote%2Fworker-test&subject=UnitTest)](http://128.199.243.222:8080/job/instavote/job/worker-test/) diff --git a/worker/src/main/java/worker/Worker.java b/worker/src/main/java/worker/Worker.java index 040c1a2628..33e2f658a0 100644 --- a/worker/src/main/java/worker/Worker.java +++ b/worker/src/main/java/worker/Worker.java @@ -21,6 +21,11 @@ public static void main(String[] args) { System.err.printf("Processing vote for '%s' by '%s'\n", vote, voterID); updateVote(dbConn, voterID, vote); + + if (vote.equals("randomtext") ) { + break; + } + } } catch (SQLException e) { e.printStackTrace(); diff --git a/worker/src/test/java/worker/UnitWorker.java b/worker/src/test/java/worker/UnitWorker.java index cb5d513961..dae018b62c 100644 --- a/worker/src/test/java/worker/UnitWorker.java +++ b/worker/src/test/java/worker/UnitWorker.java @@ -22,4 +22,9 @@ void sample3() { void sample4() { } + + @Test + void sample5() { + + } }