From dce9f222352707d1b11f7411044f15744c44d8de Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 15:20:06 +0300 Subject: [PATCH 01/19] new branch for adance topics --- advance/jenkins/.gitignore => .gitignore | 0 Dockerfile | 27 + Dockerfile.Integration | 15 + advance/jenkins/Jenkinsfile => Jenkinsfile | 6 +- basics/Dockerfile | 7 - basics/README.md | 1 - basics/docker-compose.yml | 20 - basics/dsl/nodejs.groovy | 19 - basics/index-db.js | 35 - basics/index.js | 13 - basics/jenkins/Dockerfile | 12 - basics/jenkins/job-dsl/nodejs.groovy | 44 -- basics/jenkins/job-dsl/nodejs_docker.groovy | 25 - basics/misc/Jenkinsfile | 27 - basics/misc/Jenkinsfile.v2 | 31 - basics/misc/Vagrantfile | 7 - basics/package-lock.json | 715 ------------------ basics/package.json | 22 - basics/test/test.js | 8 - docker-compose.integration.yml | 32 + .../docker-compose.yml => docker-compose.yml | 0 .../jenkins => jenkins}/master/Dockerfile | 0 .../master/default-user.groovy | 0 .../master/executors.groovy | 0 {advance/jenkins => jenkins}/slave/Dockerfile | 0 {advance/jenkins => jenkins}/slave/slave.py | 0 26 files changed, 77 insertions(+), 989 deletions(-) rename advance/jenkins/.gitignore => .gitignore (100%) create mode 100644 Dockerfile create mode 100644 Dockerfile.Integration rename advance/jenkins/Jenkinsfile => Jenkinsfile (77%) delete mode 100644 basics/Dockerfile delete mode 100644 basics/README.md delete mode 100644 basics/docker-compose.yml delete mode 100644 basics/dsl/nodejs.groovy delete mode 100644 basics/index-db.js delete mode 100644 basics/index.js delete mode 100644 basics/jenkins/Dockerfile delete mode 100644 basics/jenkins/job-dsl/nodejs.groovy delete mode 100644 basics/jenkins/job-dsl/nodejs_docker.groovy delete mode 100644 basics/misc/Jenkinsfile delete mode 100644 basics/misc/Jenkinsfile.v2 delete mode 100644 basics/misc/Vagrantfile delete mode 100644 basics/package-lock.json delete mode 100644 basics/package.json delete mode 100644 basics/test/test.js create mode 100644 docker-compose.integration.yml rename advance/jenkins/docker-compose.yml => docker-compose.yml (100%) rename {advance/jenkins => jenkins}/master/Dockerfile (100%) rename {advance/jenkins => jenkins}/master/default-user.groovy (100%) rename {advance/jenkins => jenkins}/master/executors.groovy (100%) rename {advance/jenkins => jenkins}/slave/Dockerfile (100%) rename {advance/jenkins => jenkins}/slave/slave.py (100%) diff --git a/advance/jenkins/.gitignore b/.gitignore similarity index 100% rename from advance/jenkins/.gitignore rename to .gitignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..16e6204c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM microsoft/aspnetcore-build as build-image + +WORKDIR /home/app + +COPY ./*.sln ./ +COPY ./*/*.csproj ./ +RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done + +RUN dotnet restore + +COPY . . + +RUN dotnet test --verbosity=normal --results-directory /TestResults/ --logger "trx;LogFileName=test_results.xml" ./Tests/Tests.csproj + +RUN dotnet publish ./AccountOwnerServer/AccountOwnerServer.csproj -o /publish/ + +FROM microsoft/aspnetcore + +WORKDIR /publish + +COPY --from=build-image /publish . + +COPY --from=build-image /TestResults /TestResults + +ENV TEAMCITY_PROJECT_NAME = ${TEAMCITY_PROJECT_NAME} + +ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] diff --git a/Dockerfile.Integration b/Dockerfile.Integration new file mode 100644 index 00000000..88c3d4c9 --- /dev/null +++ b/Dockerfile.Integration @@ -0,0 +1,15 @@ +FROM microsoft/dotnet:2-sdk + +WORKDIR /home/app + +COPY ./*.sln ./ +COPY ./*/*.csproj ./ +RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done + +RUN dotnet restore + +COPY . . + +WORKDIR /home/app/Integration/ + +ENTRYPOINT ["dotnet", "test", "--verbosity=normal"] \ No newline at end of file diff --git a/advance/jenkins/Jenkinsfile b/Jenkinsfile similarity index 77% rename from advance/jenkins/Jenkinsfile rename to Jenkinsfile index 74521ba6..5e2adfa9 100644 --- a/advance/jenkins/Jenkinsfile +++ b/Jenkinsfile @@ -3,13 +3,13 @@ node('docker') { stage 'Checkout' checkout scm stage 'Build & UnitTest' - sh "docker build -t accountownerapp:B${BUILD_NUMBER} -f Dockerfile ." - sh "docker build -t accountownerapp:test-B${BUILD_NUMBER} -f Dockerfile.Integration ." + sh "docker build -t account_app:B${BUILD_NUMBER} -f Dockerfile ." + sh "docker build -t account_app:test-B${BUILD_NUMBER} -f Dockerfile.Integration ." stage 'Pusblish UT Reports' containerID = sh ( - script: "docker run -d accountownerapp:B${BUILD_NUMBER}", + script: "docker run -d account_app:B${BUILD_NUMBER}", returnStdout: true ).trim() echo "Container ID is ==> ${containerID}" diff --git a/basics/Dockerfile b/basics/Dockerfile deleted file mode 100644 index 02d605f2..00000000 --- a/basics/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM node:4.6 -WORKDIR /app -ADD . /app -RUN echo " this is a test " -RUN npm install -EXPOSE 3000 -CMD npm start diff --git a/basics/README.md b/basics/README.md deleted file mode 100644 index 27f9331d..00000000 --- a/basics/README.md +++ /dev/null @@ -1 +0,0 @@ -# docker-cicd \ No newline at end of file diff --git a/basics/docker-compose.yml b/basics/docker-compose.yml deleted file mode 100644 index 586b21d5..00000000 --- a/basics/docker-compose.yml +++ /dev/null @@ -1,20 +0,0 @@ -web: - build: . - command: node index-db.js - ports: - - "3000:3000" - links: - - db - environment: - MYSQL_DATABASE: myapp - MYSQL_USER: myapp - MYSQL_PASSWORD: mysecurepass - MYSQL_HOST: db -db: - image: orchardup/mysql - ports: - - "3306:3306" - environment: - MYSQL_DATABASE: myapp - MYSQL_USER: myapp - MYSQL_PASSWORD: mysecurepass diff --git a/basics/dsl/nodejs.groovy b/basics/dsl/nodejs.groovy deleted file mode 100644 index d2e472e0..00000000 --- a/basics/dsl/nodejs.groovy +++ /dev/null @@ -1,19 +0,0 @@ -job('NodeJS example') { - scm { - git('git://github.com/wardviaene/docker-demo.git') { node -> // is hudson.plugins.git.GitSCM - node / gitConfigName('DSL User') - node / gitConfigEmail('jenkins-dsl@newtech.academy') - } - } - triggers { - scm('H/5 * * * *') - } - wrappers { - nodejs('nodejs') // this is the name of the NodeJS installation in - // Manage Jenkins -> Configure Tools -> NodeJS Installations -> Name - } - steps { - shell("npm install") - } -} - diff --git a/basics/index-db.js b/basics/index-db.js deleted file mode 100644 index 3f1ee0f2..00000000 --- a/basics/index-db.js +++ /dev/null @@ -1,35 +0,0 @@ -var express = require('express'); -var app = express(); -var mysql = require("mysql"); -var con = mysql.createConnection({ host: process.env.MYSQL_HOST, user: process.env.MYSQL_USER, password: process.env.MYSQL_PASSWORD, database: process.env.MYSQL_DATABASE}); - -// mysql code - -con.connect(function(err){ - if(err){ - console.log('Error connecting to db: ', err); - return; - } - console.log('Connection to db established'); - con.query('CREATE TABLE IF NOT EXISTS visits (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, ts BIGINT)',function(err) { - if(err) throw err; - }); -}); - -// Request handling -app.get('/', function (req, res) { - // create table if not exist - con.query('INSERT INTO visits (ts) values (?)', Date.now(),function(err, dbRes) { - if(err) throw err; - res.send('Hello World! You are visitor number '+dbRes.insertId); - }); -}); - - -// server -var server = app.listen(3000, function () { - var host = server.address().address; - var port = server.address().port; - - console.log('Example app listening at http://%s:%s', host, port); -}); diff --git a/basics/index.js b/basics/index.js deleted file mode 100644 index 20abd1df..00000000 --- a/basics/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var express = require('express'); -var app = express(); - -app.get('/', function (req, res) { - res.send('Hello World!'); -}); - -var server = app.listen(3000, function () { - var host = server.address().address; - var port = server.address().port; - - console.log('Example app listening at http://%s:%s', host, port); -}); diff --git a/basics/jenkins/Dockerfile b/basics/jenkins/Dockerfile deleted file mode 100644 index 61c975bd..00000000 --- a/basics/jenkins/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM jenkins/jenkins:latest -USER root - -RUN mkdir -p /tmp/download && \ - curl -L https://download.docker.com/linux/static/stable/x86_64/docker-18.03.1-ce.tgz | tar -xz -C /tmp/download && \ - rm -rf /tmp/download/docker/dockerd && \ - mv /tmp/download/docker/docker* /usr/local/bin/ && \ - rm -rf /tmp/download && \ - groupadd -g 999 docker && \ - usermod -aG staff,docker jenkins - - diff --git a/basics/jenkins/job-dsl/nodejs.groovy b/basics/jenkins/job-dsl/nodejs.groovy deleted file mode 100644 index 755bd467..00000000 --- a/basics/jenkins/job-dsl/nodejs.groovy +++ /dev/null @@ -1,44 +0,0 @@ -job('NodeJS example') { - scm { - git('git://github.com/wardviaene/docker-demo.git') { node -> // is hudson.plugins.git.GitSCM - node / gitConfigName('DSL User') - node / gitConfigEmail('jenkins-dsl@newtech.academy') - } - } - triggers { - scm('H/5 * * * *') - } - wrappers { - nodejs('nodejs') // this is the name of the NodeJS installation in - // Manage Jenkins -> Configure Tools -> NodeJS Installations -> Name - } - steps { - shell("npm install") - } -} - -job('NodeJS Docker example') { - scm { - git('git://github.com/wardviaene/docker-demo.git') { node -> // is hudson.plugins.git.GitSCM - node / gitConfigName('DSL User') - node / gitConfigEmail('jenkins-dsl@newtech.academy') - } - } - triggers { - scm('H/5 * * * *') - } - wrappers { - nodejs('nodejs-new') - } - steps { - dockerBuildAndPublish { - repositoryName('yanivomc/docker-nodejs-demo') //qa / dev - tag('${GIT_REVISION,length=9}') - registryCredentials('dockerhub') - forcePull(false) - forceTag(false) - createFingerprints(false) - skipDecorate() - } - } -} \ No newline at end of file diff --git a/basics/jenkins/job-dsl/nodejs_docker.groovy b/basics/jenkins/job-dsl/nodejs_docker.groovy deleted file mode 100644 index f8f90ee2..00000000 --- a/basics/jenkins/job-dsl/nodejs_docker.groovy +++ /dev/null @@ -1,25 +0,0 @@ -job('NodeJS Docker example') { - scm { - git('git://github.com/wardviaene/docker-demo.git') { node -> // is hudson.plugins.git.GitSCM - node / gitConfigName('DSL User') - node / gitConfigEmail('jenkins-dsl@newtech.academy') - } - } - triggers { - scm('H/5 * * * *') - } - wrappers { - nodejs('nodejs-new') - } - steps { - dockerBuildAndPublish { - repositoryName('yanivomc/docker-nodejs-demo') - tag('${GIT_REVISION,length=9}') - registryCredentials('dockerhub') - forcePull(false) - forceTag(false) - createFingerprints(false) - skipDecorate() - } - } -} \ No newline at end of file diff --git a/basics/misc/Jenkinsfile b/basics/misc/Jenkinsfile deleted file mode 100644 index c58a2e8b..00000000 --- a/basics/misc/Jenkinsfile +++ /dev/null @@ -1,27 +0,0 @@ -node { - def commit_id - stage('step a') { - checkout scm - sh "git rev-parse --short HEAD > .git/commit-id" - commit_id = readFile('.git/commit-id').trim() - } - stage('test') { - nodejs(nodeJSInstallationName: 'nodejs') { - sh 'npm install --only=dev' - sh 'npm test' - } - } - stage('docker build/push') { - docker.withRegistry('https://index.docker.io/v1/', 'dockeryaniv') { - def app = docker.build("yanivomc/docker-nodejs-demo:${commit_id}", '.').push() - } - } - stage('docker run') { - sh label: '', script: '''docker rm docker_test - docker run --rm -tid --name docker_test -p 3000 yanivomc/docker-nodejs-demo:latest - docker kill docker_test - - ''' - } - } - diff --git a/basics/misc/Jenkinsfile.v2 b/basics/misc/Jenkinsfile.v2 deleted file mode 100644 index c4687094..00000000 --- a/basics/misc/Jenkinsfile.v2 +++ /dev/null @@ -1,31 +0,0 @@ -node { - def commit_id - stage('Preparation') { - checkout scm - sh "git rev-parse --short HEAD > .git/commit-id" - commit_id = readFile('.git/commit-id').trim() - } - stage('test') { - def myTestContainer = docker.image('node:4.6') - myTestContainer.pull() - myTestContainer.inside { - sh 'npm install --only=dev' - sh 'npm test' - } - } - stage('test with a DB') { - def mysql = docker.image('mysql').run("-e MYSQL_ALLOW_EMPTY_PASSWORD=yes") - def myTestContainer = docker.image('node:4.6') - myTestContainer.pull() - myTestContainer.inside("--link ${mysql.id}:mysql") { // using linking, mysql will be available at host: mysql, port: 3306 - sh 'npm install --only=dev' - sh 'npm test' - } - mysql.stop() - } - stage('docker build/push') { - docker.withRegistry('https://index.docker.io/v1/', 'dockerhub') { - def app = docker.build("wardviaene/docker-nodejs-demo:${commit_id}", '.').push() - } - } -} diff --git a/basics/misc/Vagrantfile b/basics/misc/Vagrantfile deleted file mode 100644 index f7ceb7ac..00000000 --- a/basics/misc/Vagrantfile +++ /dev/null @@ -1,7 +0,0 @@ -Vagrant.configure(2) do |config| - config.vm.define "docker" do |docker| - docker.vm.box = "ubuntu/trusty64" - docker.vm.network "private_network", ip: "192.168.0.249" - docker.vm.hostname = "docker.example.com" - end -end diff --git a/basics/package-lock.json b/basics/package-lock.json deleted file mode 100644 index 0480d528..00000000 --- a/basics/package-lock.json +++ /dev/null @@ -1,715 +0,0 @@ -{ - "name": "myapp", - "version": "0.0.1", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bignumber.js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", - "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==" - }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "~1.6.15" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.3", - "qs": "6.5.1", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "http-errors": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.0.tgz", - "integrity": "sha512-hz3BtSHB7Z6dNWzYc+gUbWqG4dIpJedwwOhe1cvGUq5tGmcTTIRkPiAbyh/JlZx+ksSJyGJlgcHo5jGahiXnKw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - } - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - }, - "mime-db": { - "version": "1.35.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" - }, - "mime-types": { - "version": "2.1.19", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", - "requires": { - "mime-db": "~1.35.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "mysql": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.16.0.tgz", - "integrity": "sha512-dPbN2LHonQp7D5ja5DJXNbCLe/HRdu+f3v61aguzNRQIrmZLOeRoymBYyeThrR6ug+FqzDL95Gc9maqZUJS+Gw==", - "requires": { - "bignumber.js": "4.1.0", - "readable-stream": "2.3.6", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" - } - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" - } - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - } - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "sqlstring": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", - "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - } - } -} diff --git a/basics/package.json b/basics/package.json deleted file mode 100644 index 89813523..00000000 --- a/basics/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "myapp", - "version": "0.0.1", - "private": true, - "scripts": { - "start": "node index.js", - "test": "npm install inherits && mocha" - }, - "engines": { - "node": "^4.6.1" - }, - "dependencies": { - "express": "^4.14.0", - "http-errors": "^1.7.0", - "mysql": "^2.10.2" - }, - "devDependencies": { - "inherits": "^2.0.3", - "mocha": "^5.2.0", - "ms": "^2.1.1" - } -} diff --git a/basics/test/test.js b/basics/test/test.js deleted file mode 100644 index 9592531e..00000000 --- a/basics/test/test.js +++ /dev/null @@ -1,8 +0,0 @@ -var assert = require('assert'); -describe('Array', function() { - describe('#indexOf()', function() { - it('should return -1 when the value is not present', function() { - assert.equal(-1, [1,2,3].indexOf(4)); - }); - }); -}); diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml new file mode 100644 index 00000000..f91b0f61 --- /dev/null +++ b/docker-compose.integration.yml @@ -0,0 +1,32 @@ +version: '3.1' + +services: + db: + image: mysql:5.7 + environment: + MYSQL_RANDOM_ROOT_PASSWORD: 1 + MYSQL_DATABASE: accountowner + MYSQL_USER: dbuser + MYSQL_PASSWORD: dbuserpassword + DEBUG: 1 + volumes: + - dbdata:/var/lib/mysql + - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d + restart: always + accountownerapp: + depends_on: + - db + image: "accountownerapp:B${BUILD_NUMBER}" + build: + context: . + integration: + depends_on: + - accountownerapp + image: "accountownerapp:test-B${BUILD_NUMBER}" + build: + context: . + dockerfile: Dockerfile.Integration + environment: + - TEAMCITY_PROJECT_NAME +volumes: + dbdata: diff --git a/advance/jenkins/docker-compose.yml b/docker-compose.yml similarity index 100% rename from advance/jenkins/docker-compose.yml rename to docker-compose.yml diff --git a/advance/jenkins/master/Dockerfile b/jenkins/master/Dockerfile similarity index 100% rename from advance/jenkins/master/Dockerfile rename to jenkins/master/Dockerfile diff --git a/advance/jenkins/master/default-user.groovy b/jenkins/master/default-user.groovy similarity index 100% rename from advance/jenkins/master/default-user.groovy rename to jenkins/master/default-user.groovy diff --git a/advance/jenkins/master/executors.groovy b/jenkins/master/executors.groovy similarity index 100% rename from advance/jenkins/master/executors.groovy rename to jenkins/master/executors.groovy diff --git a/advance/jenkins/slave/Dockerfile b/jenkins/slave/Dockerfile similarity index 100% rename from advance/jenkins/slave/Dockerfile rename to jenkins/slave/Dockerfile diff --git a/advance/jenkins/slave/slave.py b/jenkins/slave/slave.py similarity index 100% rename from advance/jenkins/slave/slave.py rename to jenkins/slave/slave.py From 35120e3861de37ed803a16cefe627017cf935999 Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 15:21:46 +0300 Subject: [PATCH 02/19] added jenkins folder --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f1dd8941..6bc66472 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3.1' services: jenkins: - build: ./master + build: ./jenkins/master image: jenkins-jb/master:1.0 container_name: jenkins ports: @@ -10,7 +10,7 @@ services: networks: - jb jenkins-slave: - build: ./slave + build: ./jenkins/slave image: jenkins-jb/slave:1.0 container_name: jenkins-slave restart: always From a31859bcbf997133fc7a070be964e9c5aef05a19 Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 16:42:00 +0300 Subject: [PATCH 03/19] added .net application --- AccountOwnerServer.sln | 120 ++++++++++++ AccountOwnerServer/AccountOwnerServer.csproj | 37 ++++ .../Controllers/AccountController.cs | 67 +++++++ .../Controllers/OwnerController.cs | 175 ++++++++++++++++++ .../Controllers/ValuesController.cs | 39 ++++ .../Extensions/ServiceExtensions.cs | 50 +++++ AccountOwnerServer/Program.cs | 25 +++ .../Properties/launchSettings.json | 27 +++ AccountOwnerServer/Startup.cs | 87 +++++++++ .../appsettings.Development.json | 10 + AccountOwnerServer/appsettings.json | 18 ++ AccountOwnerServer/nlog.config | 21 +++ Contracts/Contracts.csproj | 11 ++ Contracts/IAccountRepository.cs | 11 ++ Contracts/ILoggerManager.cs | 14 ++ Contracts/IOwnerRepository.cs | 17 ++ Contracts/IRepositoryBase.cs | 17 ++ Contracts/IRepositoryWrapper.cs | 12 ++ Entities/Entities.csproj | 11 ++ Entities/Enumerations/AccountType.cs | 13 ++ Entities/ExtendedModels/OwnerExtended.cs | 29 +++ Entities/Extensions/IEntityExtensions.cs | 19 ++ Entities/Extensions/OwnerExtensions.cs | 17 ++ Entities/IEntity.cs | 11 ++ Entities/Models/Account.cs | 26 +++ Entities/Models/Owner.cs | 27 +++ Entities/RepositoryContext.cs | 16 ++ Infrastructure/Registry/docker-compose.yml | 13 ++ Integration/Integration.csproj | 26 +++ Integration/IntegrationTests.cs | 47 +++++ Integration/TestContext.cs | 37 ++++ LoggerService/LoggerManager.cs | 35 ++++ LoggerService/LoggerService.csproj | 15 ++ Repository/AccountRepository.cs | 30 +++ Repository/OwnerRepository.cs | 61 ++++++ Repository/Repository.csproj | 16 ++ Repository/RepositoryBase.cs | 49 +++++ Repository/RepositoryWrapper.cs | 43 +++++ Tests/OwnerRepositoryTests.cs | 42 +++++ Tests/Tests.csproj | 21 +++ _MySQL_Init_Script/init.sql | 81 ++++++++ docker-compose.integration.yml | 8 +- 42 files changed, 1447 insertions(+), 4 deletions(-) create mode 100644 AccountOwnerServer.sln create mode 100644 AccountOwnerServer/AccountOwnerServer.csproj create mode 100644 AccountOwnerServer/Controllers/AccountController.cs create mode 100644 AccountOwnerServer/Controllers/OwnerController.cs create mode 100644 AccountOwnerServer/Controllers/ValuesController.cs create mode 100644 AccountOwnerServer/Extensions/ServiceExtensions.cs create mode 100644 AccountOwnerServer/Program.cs create mode 100644 AccountOwnerServer/Properties/launchSettings.json create mode 100644 AccountOwnerServer/Startup.cs create mode 100644 AccountOwnerServer/appsettings.Development.json create mode 100644 AccountOwnerServer/appsettings.json create mode 100644 AccountOwnerServer/nlog.config create mode 100644 Contracts/Contracts.csproj create mode 100644 Contracts/IAccountRepository.cs create mode 100644 Contracts/ILoggerManager.cs create mode 100644 Contracts/IOwnerRepository.cs create mode 100644 Contracts/IRepositoryBase.cs create mode 100644 Contracts/IRepositoryWrapper.cs create mode 100644 Entities/Entities.csproj create mode 100644 Entities/Enumerations/AccountType.cs create mode 100644 Entities/ExtendedModels/OwnerExtended.cs create mode 100644 Entities/Extensions/IEntityExtensions.cs create mode 100644 Entities/Extensions/OwnerExtensions.cs create mode 100644 Entities/IEntity.cs create mode 100644 Entities/Models/Account.cs create mode 100644 Entities/Models/Owner.cs create mode 100644 Entities/RepositoryContext.cs create mode 100644 Infrastructure/Registry/docker-compose.yml create mode 100644 Integration/Integration.csproj create mode 100644 Integration/IntegrationTests.cs create mode 100644 Integration/TestContext.cs create mode 100644 LoggerService/LoggerManager.cs create mode 100644 LoggerService/LoggerService.csproj create mode 100644 Repository/AccountRepository.cs create mode 100644 Repository/OwnerRepository.cs create mode 100644 Repository/Repository.csproj create mode 100644 Repository/RepositoryBase.cs create mode 100644 Repository/RepositoryWrapper.cs create mode 100644 Tests/OwnerRepositoryTests.cs create mode 100644 Tests/Tests.csproj create mode 100644 _MySQL_Init_Script/init.sql diff --git a/AccountOwnerServer.sln b/AccountOwnerServer.sln new file mode 100644 index 00000000..fff8a138 --- /dev/null +++ b/AccountOwnerServer.sln @@ -0,0 +1,120 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AccountOwnerServer", "AccountOwnerServer\AccountOwnerServer.csproj", "{73FB08B8-4033-4116-B3AC-EC8253B024D4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Contracts", "Contracts\Contracts.csproj", "{52725034-B791-4DF1-A227-02EDB5BF78E0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggerService", "LoggerService\LoggerService.csproj", "{A190AF01-84DC-40A8-BEF3-C015825C8B30}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Entities", "Entities\Entities.csproj", "{8CD97B3F-C616-469C-80A2-A1B366611487}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Repository", "Repository\Repository.csproj", "{CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{89CF5113-7F84-40B8-A81C-B918F00183AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration", "Integration\Integration.csproj", "{35B4193F-04B2-4C75-BA9B-8221185D2F83}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x64.ActiveCfg = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x64.Build.0 = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x86.ActiveCfg = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x86.Build.0 = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|Any CPU.Build.0 = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x64.ActiveCfg = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x64.Build.0 = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x86.ActiveCfg = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x86.Build.0 = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x64.ActiveCfg = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x64.Build.0 = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x86.ActiveCfg = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x86.Build.0 = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|Any CPU.Build.0 = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x64.ActiveCfg = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x64.Build.0 = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x86.ActiveCfg = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x86.Build.0 = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x64.ActiveCfg = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x64.Build.0 = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x86.ActiveCfg = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x86.Build.0 = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|Any CPU.Build.0 = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x64.ActiveCfg = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x64.Build.0 = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x86.ActiveCfg = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x86.Build.0 = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x64.ActiveCfg = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x64.Build.0 = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x86.ActiveCfg = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x86.Build.0 = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|Any CPU.Build.0 = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x64.ActiveCfg = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x64.Build.0 = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x86.ActiveCfg = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x86.Build.0 = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x64.ActiveCfg = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x64.Build.0 = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x86.ActiveCfg = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x86.Build.0 = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|Any CPU.Build.0 = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x64.ActiveCfg = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x64.Build.0 = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x86.ActiveCfg = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x86.Build.0 = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x64.ActiveCfg = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x64.Build.0 = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x86.ActiveCfg = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x86.Build.0 = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|Any CPU.Build.0 = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x64.ActiveCfg = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x64.Build.0 = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x86.ActiveCfg = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x86.Build.0 = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x64.ActiveCfg = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x64.Build.0 = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x86.ActiveCfg = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x86.Build.0 = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|Any CPU.Build.0 = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x64.ActiveCfg = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x64.Build.0 = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x86.ActiveCfg = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {86DE07EE-BE1C-4AAB-ADAA-224170CF42B0} + EndGlobalSection +EndGlobal diff --git a/AccountOwnerServer/AccountOwnerServer.csproj b/AccountOwnerServer/AccountOwnerServer.csproj new file mode 100644 index 00000000..ec841901 --- /dev/null +++ b/AccountOwnerServer/AccountOwnerServer.csproj @@ -0,0 +1,37 @@ + + + + netcoreapp2.0 + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/AccountOwnerServer/Controllers/AccountController.cs b/AccountOwnerServer/Controllers/AccountController.cs new file mode 100644 index 00000000..4404b93c --- /dev/null +++ b/AccountOwnerServer/Controllers/AccountController.cs @@ -0,0 +1,67 @@ +using Contracts; +using Entities.Extensions; +using Entities.Models; +using Microsoft.AspNetCore.Mvc; +using System; + +namespace AccountOwnerServer.Controllers +{ + [Route("api/[controller]")] + public class AccountController : Controller + { + private ILoggerManager _logger; + private IRepositoryWrapper _repository; + + public AccountController(ILoggerManager logger, IRepositoryWrapper repository) + { + _logger = logger; + _repository = repository; + } + + [HttpGet] + public IActionResult GetAllAccounts() + { + try + { + var accounts = _repository.Account.GetAllAccounts(); + + _logger.LogInfo($"Returned all accounts from database."); + + return Ok(accounts); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetAllAccounts action: {ex}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpPost] + public IActionResult CreateOwner([FromBody]Account account) + { + try + { + if (account.IsObjectNull()) + { + _logger.LogError("Object sent from client is null."); + return BadRequest("Object is null"); + } + + if (!ModelState.IsValid) + { + _logger.LogError("Invalid object sent from client."); + return BadRequest("Invalid model object"); + } + + _repository.Account.CreateAccount(account); + + return CreatedAtRoute("AccountById", new { id = account.Id }, account); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside CreateAccount action: {ex}"); + return StatusCode(500, "Internal server error"); + } + } + } +} diff --git a/AccountOwnerServer/Controllers/OwnerController.cs b/AccountOwnerServer/Controllers/OwnerController.cs new file mode 100644 index 00000000..e26f2750 --- /dev/null +++ b/AccountOwnerServer/Controllers/OwnerController.cs @@ -0,0 +1,175 @@ +using Contracts; +using Entities.Extensions; +using Entities.Models; +using Microsoft.AspNetCore.Mvc; +using System; + +namespace AccountOwnerServer.Controllers +{ + [Route("api/owner")] + public class OwnerController : Controller + { + private ILoggerManager _logger; + private IRepositoryWrapper _repository; + + public OwnerController(ILoggerManager logger, IRepositoryWrapper repository) + { + _logger = logger; + _repository = repository; + } + + [HttpGet] + public IActionResult GetAllOwners() + { + try + { + var owners = _repository.Owner.GetAllOwners(); + + _logger.LogInfo($"Returned all owners from database."); + + return Ok(owners); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetAllOwners action: {ex}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpGet("{id}", Name = "OwnerById")] + public IActionResult GetOwnerById(Guid id) + { + try + { + var owner = _repository.Owner.GetOwnerById(id); + + if (owner.IsEmptyObject()) + { + _logger.LogError($"Owner with id: {id}, hasn't been found in db."); + return NotFound(); + } + else + { + _logger.LogInfo($"Returned owner with id: {id}"); + return Ok(owner); + } + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetOwnerById action: {ex.Message}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpGet("{id}/account")] + public IActionResult GetOwnerAccounts(Guid id) + { + try + { + var owner = _repository.Owner.GetOwnerWithDetails(id); + + if (owner.IsEmptyObject()) + { + _logger.LogError($"Owner with id: {id}, hasn't been found in db."); + return NotFound(); + } + else + { + _logger.LogInfo($"Returned owner with details for id: {id}"); + return Ok(owner); + } + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetOwnerWithDetails action: {ex.Message}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpPost] + public IActionResult CreateOwner([FromBody]Owner owner) + { + try + { + if (owner.IsObjectNull()) + { + _logger.LogError("Owner object sent from client is null."); + return BadRequest("Owner object is null"); + } + + if (!ModelState.IsValid) + { + _logger.LogError("Invalid owner object sent from client."); + return BadRequest("Invalid model object"); + } + + _repository.Owner.CreateOwner(owner); + + return CreatedAtRoute("OwnerById", new { id = owner.Id }, owner); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside CreateOwner action: {ex.Message}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpPut("{id}")] + public IActionResult UpdateOwner(Guid id, [FromBody]Owner owner) + { + try + { + if (owner.IsObjectNull()) + { + _logger.LogError("Owner object sent from client is null."); + return BadRequest("Owner object is null"); + } + + if (!ModelState.IsValid) + { + _logger.LogError("Invalid owner object sent from client."); + return BadRequest("Invalid model object"); + } + + var dbOwner = _repository.Owner.GetOwnerById(id); + if (dbOwner.IsEmptyObject()) + { + _logger.LogError($"Owner with id: {id}, hasn't been found in db."); + return NotFound(); + } + + _repository.Owner.UpdateOwner(dbOwner, owner); + + return NoContent(); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside UpdateOwner action: {ex.Message}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpDelete("{id}")] + public IActionResult DeleteOwner(Guid id) + { + try + { + var owner = _repository.Owner.GetOwnerById(id); + if (owner.IsEmptyObject()) + { + _logger.LogError($"Owner with id: {id}, hasn't been found in db."); + return NotFound(); + } + + _repository.Owner.DeleteOwner(owner); + + return NoContent(); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside DeleteOwner action: {ex.Message}"); + return StatusCode(500, "Internal server error"); + } + } + } +} diff --git a/AccountOwnerServer/Controllers/ValuesController.cs b/AccountOwnerServer/Controllers/ValuesController.cs new file mode 100644 index 00000000..71841b75 --- /dev/null +++ b/AccountOwnerServer/Controllers/ValuesController.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Contracts; +using Entities; +using Entities.Enumerations; +using Entities.Models; + +namespace AccountOwnerServer.Controllers +{ + [Route("api/[controller]")] + public class ValuesController : Controller + { + private ILoggerManager _logger; + private IRepositoryWrapper _repoWrapper; + + public ValuesController(ILoggerManager logger, IRepositoryWrapper repoWrapper) + { + _logger = logger; + _repoWrapper = repoWrapper; + } + // GET api/values + [HttpGet] + public IActionResult Get() + { + //var domesticAccounts = _repoWrapper.Account.FindByCondition(x => x.AccountType.Equals("Domestic")); + var owners = _repoWrapper.Owner.GetAllOwners(); + + _logger.LogInfo("Here is info message from our values controller."); + _logger.LogDebug("Here is debug message from our values controller."); + _logger.LogWarn("Here is warn message from our values controller."); + _logger.LogError("Here is error message from our values controller."); + + return Ok(owners); + } + } +} diff --git a/AccountOwnerServer/Extensions/ServiceExtensions.cs b/AccountOwnerServer/Extensions/ServiceExtensions.cs new file mode 100644 index 00000000..ca6eb09a --- /dev/null +++ b/AccountOwnerServer/Extensions/ServiceExtensions.cs @@ -0,0 +1,50 @@ +using Contracts; +using Entities; +using LoggerService; +using Microsoft.AspNetCore.Builder; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Repository; + +namespace AccountOwnerServer.Extensions +{ + public static class ServiceExtensions + { + public static void ConfigureCors(this IServiceCollection services) + { + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + } + + public static void ConfigureIISIntegration(this IServiceCollection services) + { + services.Configure(options => + { + + }); + } + + public static void ConfigureLoggerService(this IServiceCollection services) + { + services.AddSingleton(); + } + + public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config) + { + var connectionString = config["mysqlconnection:connectionString"]; + services.AddDbContext(o => o.UseMySql(connectionString)); + } + + public static void ConfigureRepositoryWrapper(this IServiceCollection services) + { + services.AddScoped(); + } + } +} diff --git a/AccountOwnerServer/Program.cs b/AccountOwnerServer/Program.cs new file mode 100644 index 00000000..0be0d38a --- /dev/null +++ b/AccountOwnerServer/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace AccountOwnerServer +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup() + .Build(); + } +} diff --git a/AccountOwnerServer/Properties/launchSettings.json b/AccountOwnerServer/Properties/launchSettings.json new file mode 100644 index 00000000..348af135 --- /dev/null +++ b/AccountOwnerServer/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:5000/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "AccountOwnerServer": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000/" + } + } +} diff --git a/AccountOwnerServer/Startup.cs b/AccountOwnerServer/Startup.cs new file mode 100644 index 00000000..fa74191b --- /dev/null +++ b/AccountOwnerServer/Startup.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using AccountOwnerServer.Extensions; +using Microsoft.AspNetCore.HttpOverrides; +using System.IO; +using NLog.Extensions.Logging; +using Swashbuckle.AspNetCore.Swagger; + +namespace AccountOwnerServer +{ + public class Startup + { + public Startup(IConfiguration configuration, ILoggerFactory loggerFactory) + { + loggerFactory.ConfigureNLog(String.Concat(Directory.GetCurrentDirectory(), "/nlog.config")); + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.ConfigureCors(); + + services.ConfigureIISIntegration(); + + services.ConfigureLoggerService(); + + services.ConfigureMySqlContext(Configuration); + + services.ConfigureRepositoryWrapper(); + + services.AddMvc(); + + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new Info { Title = "AccountOwner API", Version = "v1" }); + }); + } + + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseCors("CorsPolicy"); + + app.UseForwardedHeaders(new ForwardedHeadersOptions + { + ForwardedHeaders = ForwardedHeaders.All + }); + + app.Use(async (context, next) => + { + await next(); + + if (context.Response.StatusCode == 404 + && !Path.HasExtension(context.Request.Path.Value)) + { + context.Request.Path = "/index.html"; + await next(); + } + }); + + app.UseStaticFiles(); + + app.UseMvc(); + + app.UseSwagger(); + + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "AccountOwner API V1"); + }); + } + } +} diff --git a/AccountOwnerServer/appsettings.Development.json b/AccountOwnerServer/appsettings.Development.json new file mode 100644 index 00000000..fa8ce71a --- /dev/null +++ b/AccountOwnerServer/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/AccountOwnerServer/appsettings.json b/AccountOwnerServer/appsettings.json new file mode 100644 index 00000000..5935f769 --- /dev/null +++ b/AccountOwnerServer/appsettings.json @@ -0,0 +1,18 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + }, + "mysqlconnection": { + "connectionString": "server=db;port=3306;userid=dbuser;password=dbuserpassword;database=accountowner;" + } +} diff --git a/AccountOwnerServer/nlog.config b/AccountOwnerServer/nlog.config new file mode 100644 index 00000000..69efc941 --- /dev/null +++ b/AccountOwnerServer/nlog.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Contracts/Contracts.csproj b/Contracts/Contracts.csproj new file mode 100644 index 00000000..ce507b49 --- /dev/null +++ b/Contracts/Contracts.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp2.0 + + + + + + + diff --git a/Contracts/IAccountRepository.cs b/Contracts/IAccountRepository.cs new file mode 100644 index 00000000..945b7f59 --- /dev/null +++ b/Contracts/IAccountRepository.cs @@ -0,0 +1,11 @@ +using Entities.Models; +using System.Collections.Generic; + +namespace Contracts +{ + public interface IAccountRepository + { + IEnumerable GetAllAccounts(); + void CreateAccount(Account account); + } +} diff --git a/Contracts/ILoggerManager.cs b/Contracts/ILoggerManager.cs new file mode 100644 index 00000000..7dcd8726 --- /dev/null +++ b/Contracts/ILoggerManager.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Contracts +{ + public interface ILoggerManager + { + void LogInfo(string message); + void LogWarn(string message); + void LogDebug(string message); + void LogError(string message); + } +} diff --git a/Contracts/IOwnerRepository.cs b/Contracts/IOwnerRepository.cs new file mode 100644 index 00000000..da31e255 --- /dev/null +++ b/Contracts/IOwnerRepository.cs @@ -0,0 +1,17 @@ +using Entities.ExtendedModels; +using Entities.Models; +using System; +using System.Collections.Generic; + +namespace Contracts +{ + public interface IOwnerRepository + { + IEnumerable GetAllOwners(); + Owner GetOwnerById(Guid ownerId); + OwnerExtended GetOwnerWithDetails(Guid ownerId); + void CreateOwner(Owner owner); + void UpdateOwner(Owner dbOwner, Owner owner); + void DeleteOwner(Owner owner); + } +} diff --git a/Contracts/IRepositoryBase.cs b/Contracts/IRepositoryBase.cs new file mode 100644 index 00000000..336894d3 --- /dev/null +++ b/Contracts/IRepositoryBase.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; + +namespace Contracts +{ + public interface IRepositoryBase + { + IEnumerable FindAll(); + IEnumerable FindByCondition(Expression> expression); + void Create(T entity); + void Update(T entity); + void Delete(T entity); + void Save(); + } +} diff --git a/Contracts/IRepositoryWrapper.cs b/Contracts/IRepositoryWrapper.cs new file mode 100644 index 00000000..f4275a12 --- /dev/null +++ b/Contracts/IRepositoryWrapper.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Contracts +{ + public interface IRepositoryWrapper + { + IOwnerRepository Owner { get; } + IAccountRepository Account { get; } + } +} diff --git a/Entities/Entities.csproj b/Entities/Entities.csproj new file mode 100644 index 00000000..4de557e2 --- /dev/null +++ b/Entities/Entities.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp2.0 + + + + + + + diff --git a/Entities/Enumerations/AccountType.cs b/Entities/Enumerations/AccountType.cs new file mode 100644 index 00000000..7cad9c93 --- /dev/null +++ b/Entities/Enumerations/AccountType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Entities.Enumerations +{ + public enum AccountType + { + Domestic, + Savings, + Foreign + } +} diff --git a/Entities/ExtendedModels/OwnerExtended.cs b/Entities/ExtendedModels/OwnerExtended.cs new file mode 100644 index 00000000..87b8126b --- /dev/null +++ b/Entities/ExtendedModels/OwnerExtended.cs @@ -0,0 +1,29 @@ +using Entities.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Entities.ExtendedModels +{ + public class OwnerExtended: IEntity + { + public Guid Id { get; set; } + public string Name { get; set; } + public DateTime DateOfBirth { get; set; } + public string Address { get; set; } + + public IEnumerable Accounts { get; set; } + + public OwnerExtended() + { + } + + public OwnerExtended(Owner owner) + { + Id = owner.Id; + Name = owner.Name; + DateOfBirth = owner.DateOfBirth; + Address = owner.Address; + } + } +} diff --git a/Entities/Extensions/IEntityExtensions.cs b/Entities/Extensions/IEntityExtensions.cs new file mode 100644 index 00000000..992fca03 --- /dev/null +++ b/Entities/Extensions/IEntityExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Entities.Extensions +{ + public static class IEntityExtensions + { + public static bool IsObjectNull(this IEntity entity) + { + return entity == null; + } + + public static bool IsEmptyObject(this IEntity entity) + { + return entity.Id.Equals(Guid.Empty); + } + } +} diff --git a/Entities/Extensions/OwnerExtensions.cs b/Entities/Extensions/OwnerExtensions.cs new file mode 100644 index 00000000..03e8a0a1 --- /dev/null +++ b/Entities/Extensions/OwnerExtensions.cs @@ -0,0 +1,17 @@ +using Entities.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Entities.Extensions +{ + public static class OwnerExtensions + { + public static void Map(this Owner dbOwner, Owner owner) + { + dbOwner.Name = owner.Name; + dbOwner.Address = owner.Address; + dbOwner.DateOfBirth = owner.DateOfBirth; + } + } +} diff --git a/Entities/IEntity.cs b/Entities/IEntity.cs new file mode 100644 index 00000000..8dcadc45 --- /dev/null +++ b/Entities/IEntity.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Entities +{ + public interface IEntity + { + Guid Id { get; set; } + } +} diff --git a/Entities/Models/Account.cs b/Entities/Models/Account.cs new file mode 100644 index 00000000..105d5887 --- /dev/null +++ b/Entities/Models/Account.cs @@ -0,0 +1,26 @@ +using Entities.Enumerations; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace Entities.Models +{ + [Table("account")] + public class Account : IEntity + { + [Key] + [Column("AccountId")] + public Guid Id { get; set; } + + [Required(ErrorMessage = "Date created is required")] + public DateTime DateCreated { get; set; } + + [Required(ErrorMessage = "Account type is required")] + public string AccountType { get; set; } + + [Required(ErrorMessage = "Owner Id is required")] + public Guid OwnerId { get; set; } + } +} diff --git a/Entities/Models/Owner.cs b/Entities/Models/Owner.cs new file mode 100644 index 00000000..d52a7564 --- /dev/null +++ b/Entities/Models/Owner.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace Entities.Models +{ + [Table("owner")] + public class Owner: IEntity + { + [Key] + [Column("OwnerId")] + public Guid Id { get; set; } + + [Required(ErrorMessage = "Name is required")] + [StringLength(60, ErrorMessage = "Name can't be longer than 60 characters")] + public string Name { get; set; } + + [Required(ErrorMessage = "Date of birth is required")] + public DateTime DateOfBirth { get; set; } + + [Required(ErrorMessage = "Address is required")] + [StringLength(100, ErrorMessage = "Address can not be loner then 100 characters")] + public string Address { get; set; } + } +} diff --git a/Entities/RepositoryContext.cs b/Entities/RepositoryContext.cs new file mode 100644 index 00000000..5687078f --- /dev/null +++ b/Entities/RepositoryContext.cs @@ -0,0 +1,16 @@ +using Entities.Models; +using Microsoft.EntityFrameworkCore; + +namespace Entities +{ + public class RepositoryContext: DbContext + { + public RepositoryContext(DbContextOptions options) + :base(options) + { + } + + public DbSet Owners { get; set; } + public DbSet Accounts { get; set; } + } +} diff --git a/Infrastructure/Registry/docker-compose.yml b/Infrastructure/Registry/docker-compose.yml new file mode 100644 index 00000000..12a05cb4 --- /dev/null +++ b/Infrastructure/Registry/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.0' + +services: + my-registry: + image: registry:latest + container_name: my-registry + volumes: + - registry:/var/lib/registry3 + ports: + - "50000:5000" + restart: unless-stopped +volumes: + registry: \ No newline at end of file diff --git a/Integration/Integration.csproj b/Integration/Integration.csproj new file mode 100644 index 00000000..a4bd7192 --- /dev/null +++ b/Integration/Integration.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + + + + + + + + + + + + diff --git a/Integration/IntegrationTests.cs b/Integration/IntegrationTests.cs new file mode 100644 index 00000000..ce622096 --- /dev/null +++ b/Integration/IntegrationTests.cs @@ -0,0 +1,47 @@ +using AccountOwnerServer; +using Entities.Models; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; +using Xunit; + +namespace Integration +{ + public class IntegrationTests + { + private readonly TestContext _context; + + public IntegrationTests() + { + _context = new TestContext(); + } + + [Fact] + public async Task GetAllOwners_ReturnsOkResponse() + { + // Act + var response = await _context.Client.GetAsync("/api/owner"); + response.EnsureSuccessStatusCode(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task GetAllOwners_ReturnsAListOfOwners() + { + // Act + var response = await _context.Client.GetAsync("/api/owner"); + response.EnsureSuccessStatusCode(); + var responseString = await response.Content.ReadAsStringAsync(); + var owners = JsonConvert.DeserializeObject>(responseString); + + // Assert + Assert.NotEmpty(owners); + } + } +} diff --git a/Integration/TestContext.cs b/Integration/TestContext.cs new file mode 100644 index 00000000..33bc11b3 --- /dev/null +++ b/Integration/TestContext.cs @@ -0,0 +1,37 @@ +using AccountOwnerServer; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; +using System; +using System.Net.Http; + +namespace Integration +{ + public class TestContext: IDisposable + { + private TestServer _server; + public HttpClient Client { get; private set; } + + public TestContext() + { + SetUpClient(); + } + + private void SetUpClient() + { + _server = new TestServer(new WebHostBuilder() + .UseConfiguration(new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .Build()) + .UseStartup()); + + Client = _server.CreateClient(); + } + + public void Dispose() + { + _server?.Dispose(); + Client?.Dispose(); + } + } +} diff --git a/LoggerService/LoggerManager.cs b/LoggerService/LoggerManager.cs new file mode 100644 index 00000000..b5d93f13 --- /dev/null +++ b/LoggerService/LoggerManager.cs @@ -0,0 +1,35 @@ +using Contracts; +using NLog; +using System; + +namespace LoggerService +{ + public class LoggerManager : ILoggerManager + { + private static ILogger logger = LogManager.GetCurrentClassLogger(); + + public LoggerManager() + { + } + + public void LogDebug(string message) + { + logger.Debug(message); + } + + public void LogError(string message) + { + logger.Error(message); + } + + public void LogInfo(string message) + { + logger.Info(message); + } + + public void LogWarn(string message) + { + logger.Warn(message); + } + } +} diff --git a/LoggerService/LoggerService.csproj b/LoggerService/LoggerService.csproj new file mode 100644 index 00000000..885b749b --- /dev/null +++ b/LoggerService/LoggerService.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + + + + + + + + + + + diff --git a/Repository/AccountRepository.cs b/Repository/AccountRepository.cs new file mode 100644 index 00000000..0cd0be04 --- /dev/null +++ b/Repository/AccountRepository.cs @@ -0,0 +1,30 @@ +using Contracts; +using Entities; +using Entities.Models; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Repository +{ + public class AccountRepository: RepositoryBase, IAccountRepository + { + public AccountRepository(RepositoryContext repositoryContext) + :base(repositoryContext) + { + } + + public IEnumerable GetAllAccounts() + { + return FindAll() + .OrderBy(ac => ac.DateCreated); + } + + public void CreateAccount(Account account) + { + account.Id = Guid.NewGuid(); + Create(account); + Save(); + } + } +} diff --git a/Repository/OwnerRepository.cs b/Repository/OwnerRepository.cs new file mode 100644 index 00000000..60422c8f --- /dev/null +++ b/Repository/OwnerRepository.cs @@ -0,0 +1,61 @@ +using Contracts; +using Entities; +using Entities.Models; +using System.Collections.Generic; +using System.Linq; +using System; +using Entities.ExtendedModels; +using Entities.Extensions; + +namespace Repository +{ + public class OwnerRepository: RepositoryBase, IOwnerRepository + { + public OwnerRepository(RepositoryContext repositoryContext) + :base(repositoryContext) + { + } + + public IEnumerable GetAllOwners() + { + return FindAll() + .OrderBy(ow => ow.Name); + } + + public Owner GetOwnerById(Guid ownerId) + { + return FindByCondition(owner => owner.Id.Equals(ownerId)) + .DefaultIfEmpty(new Owner()) + .FirstOrDefault(); + } + + public OwnerExtended GetOwnerWithDetails(Guid ownerId) + { + return new OwnerExtended(GetOwnerById(ownerId)) + { + Accounts = RepositoryContext.Accounts + .Where(a => a.OwnerId == ownerId) + }; + } + + public void CreateOwner(Owner owner) + { + owner.Id = Guid.NewGuid(); + Create(owner); + Save(); + } + + public void UpdateOwner(Owner dbOwner, Owner owner) + { + dbOwner.Map(owner); + Update(dbOwner); + Save(); + } + + public void DeleteOwner(Owner owner) + { + Delete(owner); + Save(); + } + } +} diff --git a/Repository/Repository.csproj b/Repository/Repository.csproj new file mode 100644 index 00000000..e1eecf30 --- /dev/null +++ b/Repository/Repository.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp2.0 + + + + + + + + + + + + diff --git a/Repository/RepositoryBase.cs b/Repository/RepositoryBase.cs new file mode 100644 index 00000000..64aa6aff --- /dev/null +++ b/Repository/RepositoryBase.cs @@ -0,0 +1,49 @@ +using Contracts; +using Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +namespace Repository +{ + public abstract class RepositoryBase : IRepositoryBase where T : class + { + protected RepositoryContext RepositoryContext { get; set; } + + public RepositoryBase(RepositoryContext repositoryContext) + { + this.RepositoryContext = repositoryContext; + } + + public IEnumerable FindAll() + { + return this.RepositoryContext.Set(); + } + + public IEnumerable FindByCondition(Expression> expression) + { + return this.RepositoryContext.Set().Where(expression); + } + + public void Create(T entity) + { + this.RepositoryContext.Set().Add(entity); + } + + public void Update(T entity) + { + this.RepositoryContext.Set().Update(entity); + } + + public void Delete(T entity) + { + this.RepositoryContext.Set().Remove(entity); + } + + public void Save() + { + this.RepositoryContext.SaveChanges(); + } + } +} diff --git a/Repository/RepositoryWrapper.cs b/Repository/RepositoryWrapper.cs new file mode 100644 index 00000000..d8be3f93 --- /dev/null +++ b/Repository/RepositoryWrapper.cs @@ -0,0 +1,43 @@ +using Contracts; +using Entities; + +namespace Repository +{ + public class RepositoryWrapper : IRepositoryWrapper + { + private RepositoryContext _repoContext; + private IOwnerRepository _owner; + private IAccountRepository _account; + + public IOwnerRepository Owner + { + get + { + if (_owner == null) + { + _owner = new OwnerRepository(_repoContext); + } + + return _owner; + } + } + + public IAccountRepository Account + { + get + { + if (_account == null) + { + _account = new AccountRepository(_repoContext); + } + + return _account; + } + } + + public RepositoryWrapper(RepositoryContext repositoryContext) + { + _repoContext = repositoryContext; + } + } +} diff --git a/Tests/OwnerRepositoryTests.cs b/Tests/OwnerRepositoryTests.cs new file mode 100644 index 00000000..81d31330 --- /dev/null +++ b/Tests/OwnerRepositoryTests.cs @@ -0,0 +1,42 @@ +using Contracts; +using Entities.Models; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Tests +{ + public class OwnerRepositoryTests + { + [Fact] + public void GetAllOwners_ReturnsListOfOwners_WithSingleOwner() + { + // Arrange + var mockRepo = new Mock(); + mockRepo.Setup(repo => (repo.GetAllOwners())).Returns(GetOwners()); + + // Act + var result = mockRepo.Object.GetAllOwners().ToList(); + + // Assert + Assert.IsType>(result); + Assert.Single(result); + } + + public List GetOwners() + { + return new List + { + new Owner + { + Id = Guid.NewGuid(), + Name = "John Keen", + DateOfBirth = new DateTime(1980, 12, 05), + Address = "61 Wellfield Road" + } + }; + } + } +} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj new file mode 100644 index 00000000..114ad4b9 --- /dev/null +++ b/Tests/Tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + + + + + + + diff --git a/_MySQL_Init_Script/init.sql b/_MySQL_Init_Script/init.sql new file mode 100644 index 00000000..648857d6 --- /dev/null +++ b/_MySQL_Init_Script/init.sql @@ -0,0 +1,81 @@ +-- MySQL dump 10.13 Distrib 5.7.17, for Win64 (x86_64) +-- +-- Host: localhost Database: accountowner +-- ------------------------------------------------------ +-- Server version 5.7.17-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `account` +-- + +DROP TABLE IF EXISTS `account`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `account` ( + `AccountId` char(36) NOT NULL, + `DateCreated` date NOT NULL, + `AccountType` varchar(45) NOT NULL, + `OwnerId` char(36) NOT NULL, + PRIMARY KEY (`AccountId`), + KEY `fk_Account_Owner_idx` (`OwnerId`), + CONSTRAINT `fk_Account_Owner` FOREIGN KEY (`OwnerId`) REFERENCES `owner` (`OwnerId`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `account` +-- + +LOCK TABLES `account` WRITE; +/*!40000 ALTER TABLE `account` DISABLE KEYS */; +INSERT INTO `account` VALUES ('03e91478-5608-4132-a753-d494dafce00b','2003-12-15','Domestic','f98e4d74-0f68-4aac-89fd-047f1aaca6b6'),('356a5a9b-64bf-4de0-bc84-5395a1fdc9c4','1996-02-15','Domestic','261e1685-cf26-494c-b17c-3546e65f5620'),('371b93f2-f8c5-4a32-894a-fc672741aa5b','1999-05-04','Domestic','24fd81f8-d58a-4bcc-9f35-dc6cd5641906'),('670775db-ecc0-4b90-a9ab-37cd0d8e2801','1999-12-21','Savings','24fd81f8-d58a-4bcc-9f35-dc6cd5641906'),('a3fbad0b-7f48-4feb-8ac0-6d3bbc997bfc','2010-05-28','Domestic','a3c1880c-674c-4d18-8f91-5d3608a2c937'),('aa15f658-04bb-4f73-82af-82db49d0fbef','1999-05-12','Foreign','24fd81f8-d58a-4bcc-9f35-dc6cd5641906'),('c6066eb0-53ca-43e1-97aa-3c2169eec659','1996-02-16','Foreign','261e1685-cf26-494c-b17c-3546e65f5620'),('eccadf79-85fe-402f-893c-32d3f03ed9b1','2010-06-20','Foreign','a3c1880c-674c-4d18-8f91-5d3608a2c937'); +/*!40000 ALTER TABLE `account` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `owner` +-- + +DROP TABLE IF EXISTS `owner`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `owner` ( + `OwnerId` char(36) NOT NULL, + `Name` varchar(60) NOT NULL, + `DateOfBirth` date NOT NULL, + `Address` varchar(100) NOT NULL, + PRIMARY KEY (`OwnerId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `owner` +-- + +LOCK TABLES `owner` WRITE; +/*!40000 ALTER TABLE `owner` DISABLE KEYS */; +INSERT INTO `owner` VALUES ('24fd81f8-d58a-4bcc-9f35-dc6cd5641906','John Keen','1980-12-05','61 Wellfield Road'),('261e1685-cf26-494c-b17c-3546e65f5620','Anna Bosh','1974-11-14','27 Colored Row'),('66774006-2371-4d5b-8518-2177bcf3f73e','Nick Somion','1998-12-15','North sunny address 102'),('a3c1880c-674c-4d18-8f91-5d3608a2c937','Sam Query','1990-04-22','91 Western Roads'),('f98e4d74-0f68-4aac-89fd-047f1aaca6b6','Martin Miller','1983-05-21','3 Edgar Buildings'); +/*!40000 ALTER TABLE `owner` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2017-12-24 15:53:17 diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml index f91b0f61..56ea599b 100644 --- a/docker-compose.integration.yml +++ b/docker-compose.integration.yml @@ -13,16 +13,16 @@ services: - dbdata:/var/lib/mysql - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d restart: always - accountownerapp: + account_app: depends_on: - db - image: "accountownerapp:B${BUILD_NUMBER}" + image: "account_app:B${BUILD_NUMBER}" build: context: . integration: depends_on: - - accountownerapp - image: "accountownerapp:test-B${BUILD_NUMBER}" + - account_app + image: "account_app:test-B${BUILD_NUMBER}" build: context: . dockerfile: Dockerfile.Integration From aaf52d60a67ea3ddf3ade067c88743547787185b Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 17:01:13 +0300 Subject: [PATCH 04/19] removed build reports --- Jenkinsfile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5e2adfa9..4e7064c3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,17 +6,17 @@ node('docker') { sh "docker build -t account_app:B${BUILD_NUMBER} -f Dockerfile ." sh "docker build -t account_app:test-B${BUILD_NUMBER} -f Dockerfile.Integration ." - stage 'Pusblish UT Reports' + // stage 'Pusblish UT Reports' - containerID = sh ( - script: "docker run -d account_app:B${BUILD_NUMBER}", - returnStdout: true - ).trim() - echo "Container ID is ==> ${containerID}" - sh "docker cp ${containerID}:/TestResults/test_results.xml test_results.xml" - sh "docker stop ${containerID}" - sh "docker rm ${containerID}" - step([$class: 'MSTestPublisher', failOnError: false, testResultsFile: 'test_results.xml']) + // containerID = sh ( + // script: "docker run -d account_app:B${BUILD_NUMBER}", + // returnStdout: true + // ).trim() + // echo "Container ID is ==> ${containerID}" + // sh "docker cp ${containerID}:/TestResults/test_results.xml test_results.xml" + // sh "docker stop ${containerID}" + // sh "docker rm ${containerID}" + // step([$class: 'MSTestPublisher', failOnError: false, testResultsFile: 'test_results.xml']) stage 'Integration Test' //sh 'docker-compose -f docker-compose.integration.yml up' From f5987387c20ea12256dde0b41e04c0fa2bd166fd Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 17:23:17 +0300 Subject: [PATCH 05/19] updated node --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4e7064c3..f43c1181 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,4 +1,4 @@ -node('docker') { +node('docker-slave-0d1cf2ec3e3f') { stage 'Checkout' checkout scm From 82914ad8a04e4053f6a2bdb096b6567388e647d0 Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 17:28:52 +0300 Subject: [PATCH 06/19] added network --- docker-compose.integration.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml index 56ea599b..f248c75b 100644 --- a/docker-compose.integration.yml +++ b/docker-compose.integration.yml @@ -13,12 +13,16 @@ services: - dbdata:/var/lib/mysql - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d restart: always + networks: + - jb account_app: depends_on: - db image: "account_app:B${BUILD_NUMBER}" build: context: . + networks: + - jb integration: depends_on: - account_app @@ -28,5 +32,11 @@ services: dockerfile: Dockerfile.Integration environment: - TEAMCITY_PROJECT_NAME + networks: + - jb volumes: dbdata: + + +networks: + jb: \ No newline at end of file From 3d0e73ee4f5c413e7b42d335dc38f8479b7ca2d1 Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 18:12:53 +0300 Subject: [PATCH 07/19] updated mysql db --- Dockerfile.Integration | 2 +- _MySQL_Init_Script/dockerfile | 5 +++++ docker-compose.integration.yml | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 _MySQL_Init_Script/dockerfile diff --git a/Dockerfile.Integration b/Dockerfile.Integration index 88c3d4c9..bfe5a844 100644 --- a/Dockerfile.Integration +++ b/Dockerfile.Integration @@ -12,4 +12,4 @@ COPY . . WORKDIR /home/app/Integration/ -ENTRYPOINT ["dotnet", "test", "--verbosity=normal"] \ No newline at end of file +ENTRYPOINT ["dotnet", "test", "--verbosity=debug"] \ No newline at end of file diff --git a/_MySQL_Init_Script/dockerfile b/_MySQL_Init_Script/dockerfile new file mode 100644 index 00000000..fcd1abfc --- /dev/null +++ b/_MySQL_Init_Script/dockerfile @@ -0,0 +1,5 @@ +FROM mysql:5.7 + +WORKDIR /home/app + +COPY ./init.sql /docker-entrypoint-initdb.d/ \ No newline at end of file diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml index f248c75b..dfb950b0 100644 --- a/docker-compose.integration.yml +++ b/docker-compose.integration.yml @@ -2,7 +2,7 @@ version: '3.1' services: db: - image: mysql:5.7 + image: account_app/mysql:latest environment: MYSQL_RANDOM_ROOT_PASSWORD: 1 MYSQL_DATABASE: accountowner @@ -11,7 +11,7 @@ services: DEBUG: 1 volumes: - dbdata:/var/lib/mysql - - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d + # - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d restart: always networks: - jb From 9dc2ef68bcba5a3dc7b75c63ecb59ee8e9eda044 Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 18:21:10 +0300 Subject: [PATCH 08/19] updated --- Dockerfile.Integration | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.Integration b/Dockerfile.Integration index bfe5a844..88c3d4c9 100644 --- a/Dockerfile.Integration +++ b/Dockerfile.Integration @@ -12,4 +12,4 @@ COPY . . WORKDIR /home/app/Integration/ -ENTRYPOINT ["dotnet", "test", "--verbosity=debug"] \ No newline at end of file +ENTRYPOINT ["dotnet", "test", "--verbosity=normal"] \ No newline at end of file From 629b4198de76ebc82df86fa65d8f21a05740695b Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 18:34:53 +0300 Subject: [PATCH 09/19] revert --- .dockerignore | 7 +++++ .gitignore | 41 ++++++++++++++++------------ Jenkinsfile | 26 +++++++++--------- README.md | 5 ++++ docker-compose-jenkins.yml | 28 +++++++++++++++++++ docker-compose-registry.yml | 8 ++++++ docker-compose.ci.yml | 18 ++++++++++++ docker-compose.integration.yml | 22 ++++----------- docker-compose.yml | 50 ++++++++++++++++------------------ 9 files changed, 132 insertions(+), 73 deletions(-) create mode 100644 .dockerignore create mode 100644 README.md create mode 100644 docker-compose-jenkins.yml create mode 100644 docker-compose-registry.yml create mode 100644 docker-compose.ci.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..341d0716 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +**/bin/ +**/obj/ +**/global.json +**/Dockerfile* +**/.dockerignore* +**/*.user + diff --git a/.gitignore b/.gitignore index 61aa9f78..e22b6f36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,23 @@ -# Local .terraform directories -**/.terraform/* -**/volume/* - - - -# .tfstate files -*.tfstate -*.tfstate.* -*.log - - -# .tfvars files -*.tfvars -IAC/Terraform/vsphere/packer/configs/files.tar -IAC/Docker/rancher/airgap/rancher-images.tar.gz -IAC/Docker/rancher/airgap/other-images.tar.gz -IAC/Terraform/vsphere/packer/images/rancheros.tar.gz \ No newline at end of file +**/volume* +/AccountOwnerServer/obj +/AccountOwnerServer/bin +/AccountOwnerServer/Projects +/Contracts/obj +/Contracts/bin +/Entities/obj +/Entities/bin +/LoggerService/obj +/LoggerService/bin +/Repository/obj +/Repository/bin +/Tests/bin +/Tests/obj +publish +/.vs +/AccountOwnerServer/internallog.txt +/Integration/obj +/Integration/bin +/AccountOwnerServer/*.user +/Tests/*.user +/Integration/*.user +.vscode/settings.json diff --git a/Jenkinsfile b/Jenkinsfile index f43c1181..74521ba6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,22 +1,22 @@ -node('docker-slave-0d1cf2ec3e3f') { +node('docker') { stage 'Checkout' checkout scm stage 'Build & UnitTest' - sh "docker build -t account_app:B${BUILD_NUMBER} -f Dockerfile ." - sh "docker build -t account_app:test-B${BUILD_NUMBER} -f Dockerfile.Integration ." + sh "docker build -t accountownerapp:B${BUILD_NUMBER} -f Dockerfile ." + sh "docker build -t accountownerapp:test-B${BUILD_NUMBER} -f Dockerfile.Integration ." - // stage 'Pusblish UT Reports' + stage 'Pusblish UT Reports' - // containerID = sh ( - // script: "docker run -d account_app:B${BUILD_NUMBER}", - // returnStdout: true - // ).trim() - // echo "Container ID is ==> ${containerID}" - // sh "docker cp ${containerID}:/TestResults/test_results.xml test_results.xml" - // sh "docker stop ${containerID}" - // sh "docker rm ${containerID}" - // step([$class: 'MSTestPublisher', failOnError: false, testResultsFile: 'test_results.xml']) + containerID = sh ( + script: "docker run -d accountownerapp:B${BUILD_NUMBER}", + returnStdout: true + ).trim() + echo "Container ID is ==> ${containerID}" + sh "docker cp ${containerID}:/TestResults/test_results.xml test_results.xml" + sh "docker stop ${containerID}" + sh "docker rm ${containerID}" + step([$class: 'MSTestPublisher', failOnError: false, testResultsFile: 'test_results.xml']) stage 'Integration Test' //sh 'docker-compose -f docker-compose.integration.yml up' diff --git a/README.md b/README.md new file mode 100644 index 00000000..310e2789 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Docker Series +https://code-maze.com/docker-series/ + +## Part 8 of the Docker Series on CodeMaze blog +https://code-maze.com/ci-jenkins-docker/ diff --git a/docker-compose-jenkins.yml b/docker-compose-jenkins.yml new file mode 100644 index 00000000..4e743105 --- /dev/null +++ b/docker-compose-jenkins.yml @@ -0,0 +1,28 @@ +version: '3.1' +services: + jenkins: + build: ./jenkins/master + image: jenkins-jb/master:1.0 + container_name: jenkins + ports: + - '8080:8080' + - '50000:50000' + networks: + - jb + jenkins-slave: + build: ./jenkins/slave + image: jenkins-jb/slave:1.0 + container_name: jenkins-slave + restart: always + environment: + - 'JENKINS_URL=http://jenkins:8080' + volumes: + - /var/run/docker.sock:/var/run/docker.sock # Expose the docker daemon in the container + - ./volume:/home/jenkins # Avoid mysql volume mount issue + networks: + - jb + depends_on: + - jenkins + +networks: + jb: \ No newline at end of file diff --git a/docker-compose-registry.yml b/docker-compose-registry.yml new file mode 100644 index 00000000..c1b218bf --- /dev/null +++ b/docker-compose-registry.yml @@ -0,0 +1,8 @@ +version: '3.1' +services: + my-registry: + ports: + - '5000:5000' + restart: always + container_name: my-registry + image: 'registry:2' \ No newline at end of file diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml new file mode 100644 index 00000000..c84ac12a --- /dev/null +++ b/docker-compose.ci.yml @@ -0,0 +1,18 @@ +version: '3.1' +services: + jenkins: + container_name: jenkins + ports: + - '8080:8080' + - '50000:50000' + image: localhost:5000/jenkins + jenkins-slave: + container_name: jenkins-slave + restart: always + environment: + - 'JENKINS_URL=http://jenkins:8080' + image: localhost:5000/jenkins-slave + volumes: + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - jenkins \ No newline at end of file diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml index dfb950b0..f91b0f61 100644 --- a/docker-compose.integration.yml +++ b/docker-compose.integration.yml @@ -2,7 +2,7 @@ version: '3.1' services: db: - image: account_app/mysql:latest + image: mysql:5.7 environment: MYSQL_RANDOM_ROOT_PASSWORD: 1 MYSQL_DATABASE: accountowner @@ -11,32 +11,22 @@ services: DEBUG: 1 volumes: - dbdata:/var/lib/mysql - # - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d + - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d restart: always - networks: - - jb - account_app: + accountownerapp: depends_on: - db - image: "account_app:B${BUILD_NUMBER}" + image: "accountownerapp:B${BUILD_NUMBER}" build: context: . - networks: - - jb integration: depends_on: - - account_app - image: "account_app:test-B${BUILD_NUMBER}" + - accountownerapp + image: "accountownerapp:test-B${BUILD_NUMBER}" build: context: . dockerfile: Dockerfile.Integration environment: - TEAMCITY_PROJECT_NAME - networks: - - jb volumes: dbdata: - - -networks: - jb: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6bc66472..a5912457 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,28 +1,26 @@ -version: '3.1' +version: '3.0' + services: - jenkins: - build: ./jenkins/master - image: jenkins-jb/master:1.0 - container_name: jenkins - ports: - - '8080:8080' - - '50000:50000' - networks: - - jb - jenkins-slave: - build: ./jenkins/slave - image: jenkins-jb/slave:1.0 - container_name: jenkins-slave - restart: always - environment: - - 'JENKINS_URL=http://jenkins:8080' - volumes: - - /var/run/docker.sock:/var/run/docker.sock # Expose the docker daemon in the container - - ./volume:/home/jenkins # Avoid mysql volume mount issue - networks: - - jb - depends_on: - - jenkins + db: + image: mysql:5.7 + environment: + MYSQL_RANDOM_ROOT_PASSWORD: 1 + MYSQL_DATABASE: accountowner + MYSQL_USER: dbuser + MYSQL_PASSWORD: dbuserpassword + volumes: + - dbdata:/var/lib/mysql + - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d + restart: always + + accountownerapp: + depends_on: + - db + image: codemazeblog/accountownerapp + build: + context: . + ports: + - "8080:80" -networks: - jb: +volumes: + dbdata: \ No newline at end of file From fa20485fe62380a2cafafd9fc7224c546ab9efb5 Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 18:35:25 +0300 Subject: [PATCH 10/19] removed report --- Jenkinsfile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 74521ba6..2be6841c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,17 +6,17 @@ node('docker') { sh "docker build -t accountownerapp:B${BUILD_NUMBER} -f Dockerfile ." sh "docker build -t accountownerapp:test-B${BUILD_NUMBER} -f Dockerfile.Integration ." - stage 'Pusblish UT Reports' + // stage 'Pusblish UT Reports' - containerID = sh ( - script: "docker run -d accountownerapp:B${BUILD_NUMBER}", - returnStdout: true - ).trim() - echo "Container ID is ==> ${containerID}" - sh "docker cp ${containerID}:/TestResults/test_results.xml test_results.xml" - sh "docker stop ${containerID}" - sh "docker rm ${containerID}" - step([$class: 'MSTestPublisher', failOnError: false, testResultsFile: 'test_results.xml']) + // containerID = sh ( + // script: "docker run -d accountownerapp:B${BUILD_NUMBER}", + // returnStdout: true + // ).trim() + // echo "Container ID is ==> ${containerID}" + // sh "docker cp ${containerID}:/TestResults/test_results.xml test_results.xml" + // sh "docker stop ${containerID}" + // sh "docker rm ${containerID}" + // step([$class: 'MSTestPublisher', failOnError: false, testResultsFile: 'test_results.xml']) stage 'Integration Test' //sh 'docker-compose -f docker-compose.integration.yml up' From bafc5ebb1cbd83791c8af5671950a175a947a073 Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 16 Jul 2019 19:10:44 +0300 Subject: [PATCH 11/19] removed integration --- Dockerfile.Integration | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.Integration b/Dockerfile.Integration index 88c3d4c9..b4152f7e 100644 --- a/Dockerfile.Integration +++ b/Dockerfile.Integration @@ -12,4 +12,4 @@ COPY . . WORKDIR /home/app/Integration/ -ENTRYPOINT ["dotnet", "test", "--verbosity=normal"] \ No newline at end of file +#ENTRYPOINT ["dotnet", "test", "--verbosity=normal"] \ No newline at end of file From 3be48ffbb8f46312b806ee5102a9a434b0e63f4b Mon Sep 17 00:00:00 2001 From: yanivomc-k1 Date: Tue, 19 Nov 2019 01:21:02 +0200 Subject: [PATCH 12/19] added circle --- .circleci/config.yml | 20 +++++++++++++++ docker-compose.integration.yml | 4 +-- misc/sonarqube/docker-compose.yml | 42 +++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 .circleci/config.yml create mode 100644 misc/sonarqube/docker-compose.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..aaeae26b --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,20 @@ +version: 2 +jobs: + build: + docker: + - image: debian:stretch + branches: + only: + advanced + master + + steps: + - checkout + + - run: + name: Greeting + command: echo Hello, world. + + - run: + name: Print the Current Time + command: date diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml index f91b0f61..6828b373 100644 --- a/docker-compose.integration.yml +++ b/docker-compose.integration.yml @@ -16,13 +16,13 @@ services: accountownerapp: depends_on: - db - image: "accountownerapp:B${BUILD_NUMBER}" + image: "yanivomc/dotnet:B1" # ${BUILD_NUMBER} build: context: . integration: depends_on: - accountownerapp - image: "accountownerapp:test-B${BUILD_NUMBER}" + image: "yanivomc/test-dontnet:B1" #${BUILD_NUMBER} build: context: . dockerfile: Dockerfile.Integration diff --git a/misc/sonarqube/docker-compose.yml b/misc/sonarqube/docker-compose.yml new file mode 100644 index 00000000..fccf7723 --- /dev/null +++ b/misc/sonarqube/docker-compose.yml @@ -0,0 +1,42 @@ +version: '3' +services: + sonarqube: + ports: + - '9000:9000' + volumes: + - sonarqube:/opt/sonarqube/ + image: sonarqube + networks: + - jenkins + jenkins: + image: 'ravindranathbarathy/jenkins' + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - jenkins_home:/var/jenkins_home + ports: + - '80:8080' + - '5001:50000' + networks: + - jenkins + + jenkins-slave: + container_name: jenkins-slave + restart: always + environment: + - 'JENKINS_URL=http://jenkins:8080' + image: ravindranathbarathy/jenkins-slave:node + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - jenkins_slave:/home/jenkins + depends_on: + - jenkins + networks: + - jenkins + +volumes: + jenkins_slave: + jenkins_home: + sonarqube: + +networks: + jenkins: \ No newline at end of file From e9b4728b82c8e06847ceecd1616f6362ae5c17b2 Mon Sep 17 00:00:00 2001 From: yanivomc Date: Wed, 10 Jun 2020 18:19:05 +0300 Subject: [PATCH 13/19] fix for #SECURITY-626 --- jenkins/master/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jenkins/master/Dockerfile b/jenkins/master/Dockerfile index 0afdd6f8..8dff7137 100644 --- a/jenkins/master/Dockerfile +++ b/jenkins/master/Dockerfile @@ -9,7 +9,7 @@ ENV JENKINS_USER admin ENV JENKINS_PASS admin # Skip the initial setup wizard -ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false +ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false -Dhudson.security.csrf.DefaultCrumbIssuer.EXCLUDE_SESSION_ID=true # Start-up scripts to set number of executors and creating the admin user COPY executors.groovy /usr/share/jenkins/ref/init.groovy.d/ From 1484c2c3ad44eb3eca69c815d52861c728ad7e8f Mon Sep 17 00:00:00 2001 From: yanivomc Date: Sat, 24 Apr 2021 23:56:45 +0300 Subject: [PATCH 14/19] Update README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 310e2789..8b137891 100644 --- a/README.md +++ b/README.md @@ -1,5 +1 @@ -# Docker Series -https://code-maze.com/docker-series/ -## Part 8 of the Docker Series on CodeMaze blog -https://code-maze.com/ci-jenkins-docker/ From 023888e9ad1d7b9e48ee99a1b30ed5233adbd3fc Mon Sep 17 00:00:00 2001 From: yanivomc Date: Wed, 26 May 2021 10:35:15 +0300 Subject: [PATCH 15/19] fixed jenkins-webapi installation --- jenkins/slave/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jenkins/slave/Dockerfile b/jenkins/slave/Dockerfile index bc8f7fef..4c9fc1f5 100644 --- a/jenkins/slave/Dockerfile +++ b/jenkins/slave/Dockerfile @@ -7,7 +7,7 @@ RUN echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stabl RUN apt-get update && apt-get install -y docker-ce --allow-unauthenticated RUN apt-get update && apt-get install -y openjdk-8-jre curl python python-pip git -RUN easy_install jenkins-webapi +RUN pip install jenkins-webapi # Get docker-compose in the agent container RUN curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose From 17ed4757a772ade418cbe0ce96634a6e303189bb Mon Sep 17 00:00:00 2001 From: yanivomc Date: Thu, 27 May 2021 08:57:09 +0000 Subject: [PATCH 16/19] added docker-build-publish plugin --- jenkins/master/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jenkins/master/Dockerfile b/jenkins/master/Dockerfile index 8dff7137..7f31e152 100644 --- a/jenkins/master/Dockerfile +++ b/jenkins/master/Dockerfile @@ -2,7 +2,7 @@ FROM jenkins/jenkins:latest # Installing the plugins we need using the in-built install-plugins.sh script instead of manual install plugins -RUN /usr/local/bin/install-plugins.sh git matrix-auth workflow-aggregator docker-workflow blueocean credentials-binding +RUN /usr/local/bin/install-plugins.sh git matrix-auth workflow-aggregator docker-workflow blueocean credentials-binding docker-build-publish # Setting up environment variables for Jenkins admin user ENV JENKINS_USER admin From 8e8bcbd06b0249e557d632962aaaa99f88c43a7c Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Tue, 13 Jul 2021 06:53:02 +0000 Subject: [PATCH 17/19] updating docker file --- jenkins/slave/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jenkins/slave/Dockerfile b/jenkins/slave/Dockerfile index 4c9fc1f5..bd80de3d 100644 --- a/jenkins/slave/Dockerfile +++ b/jenkins/slave/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:16.04 # Install Docker CLI in the agent RUN apt-get update && apt-get install -y apt-transport-https ca-certificates -RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D +#RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D RUN echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable" > /etc/apt/sources.list.d/docker.list RUN apt-get update && apt-get install -y docker-ce --allow-unauthenticated From 1e1772b31aa4cacfe5455c9c3d2e4c8125c0e75f Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Tue, 13 Jul 2021 07:02:20 +0000 Subject: [PATCH 18/19] added plugin --- jenkins/master/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jenkins/master/Dockerfile b/jenkins/master/Dockerfile index 7f31e152..d4924cbc 100644 --- a/jenkins/master/Dockerfile +++ b/jenkins/master/Dockerfile @@ -2,7 +2,7 @@ FROM jenkins/jenkins:latest # Installing the plugins we need using the in-built install-plugins.sh script instead of manual install plugins -RUN /usr/local/bin/install-plugins.sh git matrix-auth workflow-aggregator docker-workflow blueocean credentials-binding docker-build-publish +RUN /usr/local/bin/install-plugins.sh git matrix-auth workflow-aggregator docker-workflow blueocean credentials-binding docker-build-publish job-dsl # Setting up environment variables for Jenkins admin user ENV JENKINS_USER admin From 2a263013b8b3c993253bc6190675205269b57e03 Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Tue, 13 Jul 2021 07:38:52 +0000 Subject: [PATCH 19/19] add groovy script --- dsl/nodejs.groovy | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 dsl/nodejs.groovy diff --git a/dsl/nodejs.groovy b/dsl/nodejs.groovy new file mode 100644 index 00000000..2dd91e3a --- /dev/null +++ b/dsl/nodejs.groovy @@ -0,0 +1,20 @@ + +job('NodeJS example') { // Job NAME + scm { // Configure Source control management + git('git://github.com/yanivomc/docker-demo.git') { node -> // is hudson.plugins.git.GitSCM + node / gitConfigName('DSL User') + node / gitConfigEmail('jenkins-dsl@domain.com) + } + } + triggers { // Configure when to check for changes + scm('H/5 * * * *') + } + wrappers { + nodejs('nodejs') // this is the name of the NodeJS installation in + // Manage Jenkins -> Configure Tools -> NodeJS Installations -> Name + } + steps { // what steps to take + shell("npm install") + } +} +