diff --git a/Jenkinsfile b/Jenkinsfile index 1550c92..f8d7b56 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,7 +5,7 @@ pipeline { environment { DOCKER_TLS_VERIFY='1' COMPOSE_TLS_VERSION='TLSv1_2' - DOCKER_CERT_PATH='/home/jenkins/admincerts' + DOCKER_CERT_PATH='/home/jenkins/jenkinscerts' DOCKER_HOST='tcp://:443' DTR_FQDN_PORT=':4443' } @@ -14,16 +14,21 @@ pipeline { stage('Build') { environment { DTR_ACCESS_KEY = credentials('jenkins-dtr-access-token') + MAJORMINOR = '0.0' } steps { - script { - docker image build -t ${DTR_FQDN_PORT}/engineering/db:1.0 database - docker image build -t ${DTR_FQDN_PORT}/engineering/api:rc-1.0-build-${BUILD_ID} api - docker login -u jenkins -p ${DTR_ACCESS_KEY} ${DTR_FQDN_PORT} - docker image push ${DTR_FQDN_PORT}/engineering/db:1.0 - docker image push ${DTR_FQDN_PORT}/engineering/api:rc-1.0-build-${BUILD_ID} - } + sh 'docker image build -t ${DTR_FQDN_PORT}/engineering/api-build:rc-${MAJORMINOR}.${BUILD_ID} api' + sh 'docker image build --target test -t ${DTR_FQDN_PORT}/engineering/api-build:unittest-${MAJORMINOR}.${BUILD_ID} api' + sh 'docker login -u jenkins -p ${DTR_ACCESS_KEY} ${DTR_FQDN_PORT}' + sh 'docker image push ${DTR_FQDN_PORT}/engineering/api-build:rc-${MAJORMINOR}.${BUILD_ID}' + sh 'docker image push ${DTR_FQDN_PORT}/engineering/api-build:unittest-${MAJORMINOR}.${BUILD_ID}' } } } + + post { + always{ + sh 'rm -rf ${WORKSPACE}/*' + } + } } diff --git a/Jenkinsfile-testing b/Jenkinsfile-testing new file mode 100644 index 0000000..3b73bbe --- /dev/null +++ b/Jenkinsfile-testing @@ -0,0 +1,32 @@ +pipeline { + + agent any + + environment { + DOCKER_TLS_VERIFY='1' + COMPOSE_TLS_VERSION='TLSv1_2' + DOCKER_CERT_PATH='/home/jenkins/jenkinscerts' + DOCKER_HOST='tcp://:443' + DTR_FQDN_PORT=':4443' + KUBECONFIG='/home/jenkins/jenkinscerts/kube.yml' + } + + stages { + stage('Unit') { + environment { + DTR_ACCESS_KEY = credentials('jenkins-dtr-access-token') + } + steps { + sh 'docker login -u jenkins -p ${DTR_ACCESS_KEY} ${DTR_FQDN_PORT}' + sh 'docker image pull ${DTR_FQDN_PORT}/engineering/api-test:${TAG}' + sh 'docker container run ${DTR_FQDN_PORT}/engineering/api-test:${TAG}' + } + } + } + + post { + always{ + sh 'rm -rf ${WORKSPACE}/*' + } + } +} diff --git a/api/Dockerfile b/api/Dockerfile index 210b75a..cefca3d 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -5,9 +5,15 @@ RUN mvn -B -f pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency:res COPY . . RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package -DskipTests +FROM maven:3.6.3-jdk-8 AS test +WORKDIR /usr/src/ddev +COPY . . +CMD ["mvn", "-f", "unit-pom.xml", "clean", "test"] + FROM java:8-jdk-alpine RUN adduser -Dh /home/gordon gordon WORKDIR /app COPY --from=appserver /usr/src/ddev/target/ddev-0.0.1-SNAPSHOT.jar . ENTRYPOINT ["java", "-jar", "/app/ddev-0.0.1-SNAPSHOT.jar"] CMD ["--spring.profiles.active=postgres"] + diff --git a/api/Dockerfile-dev b/api/Dockerfile-dev deleted file mode 100644 index 5883627..0000000 --- a/api/Dockerfile-dev +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:latest AS appserver -WORKDIR /usr/src/ddev -COPY pom.xml . -RUN mvn -B -f pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency:resolve -COPY . . -RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package -DskipTests - -FROM java:8-jdk-alpine -RUN adduser -Dh /home/gordon gordon -WORKDIR /app -COPY --from=appserver /usr/src/ddev/target/ddev-0.0.1-SNAPSHOT.jar . -ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005","-jar", "/app/ddev-0.0.1-SNAPSHOT.jar"] -CMD ["--spring.profiles.active=postgres"] \ No newline at end of file diff --git a/api/integration/Dockerfile b/api/integration/Dockerfile new file mode 100644 index 0000000..cde5365 --- /dev/null +++ b/api/integration/Dockerfile @@ -0,0 +1,6 @@ +FROM node:8-alpine +WORKDIR /app +COPY package.json . +RUN npm install +COPY . . +CMD npm run test diff --git a/api/integration/api-spec.js b/api/integration/api-spec.js new file mode 100644 index 0000000..a0db27f --- /dev/null +++ b/api/integration/api-spec.js @@ -0,0 +1,12 @@ +var request = require('request'); +var base_url = "http://api-ingress:8080/"; + +describe("When testing 'api/products/1'", function(){ + it("should respond with entry for 'resistor'", function(done) { + request(base_url + 'api/products/1', function(error, response, body){ + product = JSON.parse(body) + expect(product["description"]).toMatch('resistor'); + done(); + }); + }); +}); diff --git a/api/integration/package.json b/api/integration/package.json new file mode 100644 index 0000000..e6685d1 --- /dev/null +++ b/api/integration/package.json @@ -0,0 +1,14 @@ +{ + "name": "api-tests-java", + "version": "1.0.0", + "main": "server.js", + "scripts": { + "test": "jasmine-node *.js", + "start": "node server.js" + }, + "dependencies": { + "express": "^4.15.2", + "jasmine-node": "^1.14.5", + "request": "^2.81.0" + } +} diff --git a/api/pom.xml b/api/pom.xml index 1984e06..cd9e016 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -92,6 +92,16 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + + **/unit.java + + + \ No newline at end of file diff --git a/api/src/test/java/unit.java b/api/src/test/java/unit.java new file mode 100644 index 0000000..f3d7654 --- /dev/null +++ b/api/src/test/java/unit.java @@ -0,0 +1,12 @@ +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import com.docker.ddev.model.Product; + +class apiUnitTests { + + @Test + void justAnExample() { + Product testProd = new Product((long)9999, "testWidget", 19.95); + assertEquals(testProd.getProductId(), 9999); + } +} diff --git a/api/unit-pom.xml b/api/unit-pom.xml new file mode 100644 index 0000000..91c67a5 --- /dev/null +++ b/api/unit-pom.xml @@ -0,0 +1,114 @@ + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 1.5.3.RELEASE + + + com.docker.ddev + ddev + 0.0.1-SNAPSHOT + ddev + + + 1.8 + 1.4.187 + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework + spring-core + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.zaxxer + HikariCP + + + + com.h2database + h2 + + + + org.postgresql + postgresql + + + + org.hibernate + hibernate-c3p0 + 5.2.10.Final + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework + spring-jdbc + + + com.googlecode.json-simple + json-simple + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.boot + spring-boot-devtools + + + + org.apache.commons + commons-lang3 + 3.0 + + + org.junit.jupiter + junit-jupiter-api + 5.4.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.4.2 + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + + \ No newline at end of file diff --git a/app.yaml b/app.yaml deleted file mode 100644 index 188ef5f..0000000 --- a/app.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: db -spec: - replicas: 1 - selector: - matchLabels: - app: db - template: - metadata: - labels: - app: db - spec: - containers: - - name: postgres - image: ci_db:latest ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api -spec: - replicas: 1 - selector: - matchLabels: - app: api - template: - metadata: - labels: - app: api - spec: - containers: - - name: springboot - image: ci_api:latest ---- -apiVersion: v1 -kind: Service -metadata: - name: database -spec: - selector: - app: db - ports: - - port: 5432 - targetPort: 5432 ---- -apiVersion: v1 -kind: Service -metadata: - name: api-ingress -spec: - type: NodePort - selector: - app: api - ports: - - port: 8080 - targetPort: 8080 diff --git a/database/Dockerfile b/database/Dockerfile index 8797f2f..60914dc 100644 --- a/database/Dockerfile +++ b/database/Dockerfile @@ -10,4 +10,5 @@ ADD docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/ # Default values for passwords and database name. Can be overridden on docker run ENV POSTGRES_USER gordonuser +ENV POSTGRES_PASSWORD password ENV POSTGRES_DB ddev diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000..3cc7f2f --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: demochart +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: 1.16.0 diff --git a/helm/templates/api.deploy.yaml b/helm/templates/api.deploy.yaml new file mode 100644 index 0000000..b8fa42c --- /dev/null +++ b/helm/templates/api.deploy.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api +spec: + replicas: 1 + selector: + matchLabels: + app: api + template: + metadata: + labels: + app: api + spec: + containers: + - name: springboot + image: {{ .Values.DTR.FQDN }}:{{ .Values.DTR.port }}/{{ .Values.API.repo }}:{{ .Values.API.tag }} + livenessProbe: + httpGet: + path: /api/products/1 + port: 8080 + initialDelaySeconds: 20 + periodSeconds: 5 diff --git a/helm/templates/api.service.yaml b/helm/templates/api.service.yaml new file mode 100644 index 0000000..b0309fe --- /dev/null +++ b/helm/templates/api.service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-ingress +spec: + type: NodePort + selector: + app: api + ports: + - port: 8080 + targetPort: 8080 diff --git a/helm/templates/db.deploy.yaml b/helm/templates/db.deploy.yaml new file mode 100644 index 0000000..d3f9e90 --- /dev/null +++ b/helm/templates/db.deploy.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: db +spec: + replicas: 1 + selector: + matchLabels: + app: db + template: + metadata: + labels: + app: db + spec: + containers: + - name: postgres + image: {{ .Values.DTR.FQDN }}:{{ .Values.DTR.port }}/engineering/db:{{ .Values.DB.tag }} diff --git a/helm/templates/db.service.yaml b/helm/templates/db.service.yaml new file mode 100644 index 0000000..7138c32 --- /dev/null +++ b/helm/templates/db.service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: database +spec: + selector: + app: db + ports: + - port: 5432 + targetPort: 5432 diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..681ffbe --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,10 @@ +DTR: + FQDN: + port: 4443 + +DB: + tag: '1.0' + +API: + repo: 'engineering/api-build' + tag: 'demo'