From f8bda55259f1fbe7712b4fa6ea9fb3e28e1879af Mon Sep 17 00:00:00 2001 From: Rajvir Bains Date: Sat, 23 Nov 2019 22:42:41 -0800 Subject: [PATCH 1/2] agri nmp new bcdk pipeline changes --- .gitattributes | 10 + .gitignore | 1 + .jenkins/.pipeline/.nvmrc | 1 + .jenkins/.pipeline/build.js | 5 + .jenkins/.pipeline/clean.js | 5 + .jenkins/.pipeline/deploy.js | 5 + .jenkins/.pipeline/lib/build.js | 36 +++ .jenkins/.pipeline/lib/clean.js | 37 +++ .jenkins/.pipeline/lib/config.js | 19 ++ .jenkins/.pipeline/lib/deploy.js | 44 +++ .jenkins/.pipeline/npmw | 12 + .jenkins/.pipeline/package-lock.json | 46 +++ .jenkins/.pipeline/package.json | 23 ++ .jenkins/Jenkinsfile | 57 ++++ .jenkins/README.md | 40 +++ .jenkins/docker/Dockerfile | 11 + .../configuration/jobs/_jenkins/config.xml | 64 ++++ .../jenkins/configuration/jobs/nmp/config.xml | 64 ++++ .jenkins/openshift/build-master.yaml | 81 +++++ .jenkins/openshift/build-slave.yaml | 110 +++++++ .jenkins/openshift/deploy-master.yaml | 297 ++++++++++++++++++ .jenkins/openshift/deploy-prereq.yaml | 31 ++ .jenkins/openshift/deploy-slave.yaml | 164 ++++++++++ .jenkins/openshift/secrets.json | 50 +++ .pipeline/.nvmrc | 1 + .pipeline/build.js | 5 + .pipeline/clean.js | 5 + .pipeline/deploy.js | 5 + .pipeline/lib/build.js | 43 +++ .pipeline/lib/clean.js | 37 +++ .pipeline/lib/config.js | 20 ++ .pipeline/lib/deploy.js | 35 +++ .pipeline/npmw | 12 + .pipeline/package-lock.json | 46 +++ .pipeline/package.json | 23 ++ .vscode/launch.json | 48 +++ .yo-rc.json | 56 ++++ Jenkinsfile | 101 ++++-- OpenShift/dotnet-21-node.bc.json | 35 ++- OpenShift/dotnet-21.bc.json | 24 +- OpenShift/nmp.bc.json | 51 +-- OpenShift/nmp.dc.json | 134 ++++---- OpenShift/postgresql.dc.json | 236 +++++++------- 43 files changed, 1892 insertions(+), 238 deletions(-) create mode 100644 .gitattributes create mode 100644 .jenkins/.pipeline/.nvmrc create mode 100644 .jenkins/.pipeline/build.js create mode 100644 .jenkins/.pipeline/clean.js create mode 100644 .jenkins/.pipeline/deploy.js create mode 100644 .jenkins/.pipeline/lib/build.js create mode 100644 .jenkins/.pipeline/lib/clean.js create mode 100644 .jenkins/.pipeline/lib/config.js create mode 100644 .jenkins/.pipeline/lib/deploy.js create mode 100644 .jenkins/.pipeline/npmw create mode 100644 .jenkins/.pipeline/package-lock.json create mode 100644 .jenkins/.pipeline/package.json create mode 100644 .jenkins/Jenkinsfile create mode 100644 .jenkins/README.md create mode 100644 .jenkins/docker/Dockerfile create mode 100644 .jenkins/docker/contrib/jenkins/configuration/jobs/_jenkins/config.xml create mode 100644 .jenkins/docker/contrib/jenkins/configuration/jobs/nmp/config.xml create mode 100644 .jenkins/openshift/build-master.yaml create mode 100644 .jenkins/openshift/build-slave.yaml create mode 100644 .jenkins/openshift/deploy-master.yaml create mode 100644 .jenkins/openshift/deploy-prereq.yaml create mode 100644 .jenkins/openshift/deploy-slave.yaml create mode 100644 .jenkins/openshift/secrets.json create mode 100644 .pipeline/.nvmrc create mode 100644 .pipeline/build.js create mode 100644 .pipeline/clean.js create mode 100644 .pipeline/deploy.js create mode 100644 .pipeline/lib/build.js create mode 100644 .pipeline/lib/clean.js create mode 100644 .pipeline/lib/config.js create mode 100644 .pipeline/lib/deploy.js create mode 100644 .pipeline/npmw create mode 100644 .pipeline/package-lock.json create mode 100644 .pipeline/package.json create mode 100644 .vscode/launch.json create mode 100644 .yo-rc.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..c7735db14 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +* text eol=lf +*.[bB][aA][tT] text eol=crlf +*.[cC][mM][dD] text eol=crlf +*.[pP][sS][1] text eol=crlf +*.[pP][nN][gG] binary +*.[tT][tT][fF] binary +*.[eE][oO][tT] binary +*.[jJ][pP][gG] binary +*.[jJ][pP][eE][gG] binary +*.[dD][bB] binary diff --git a/.gitignore b/.gitignore index 8f71b8f6f..7a43bd985 100644 --- a/.gitignore +++ b/.gitignore @@ -283,3 +283,4 @@ functional-tests/build/* #MacOS stuff .DS_Store +node_modules/ diff --git a/.jenkins/.pipeline/.nvmrc b/.jenkins/.pipeline/.nvmrc new file mode 100644 index 000000000..6b12bc745 --- /dev/null +++ b/.jenkins/.pipeline/.nvmrc @@ -0,0 +1 @@ +v10.15.2 \ No newline at end of file diff --git a/.jenkins/.pipeline/build.js b/.jenkins/.pipeline/build.js new file mode 100644 index 000000000..3ac899f86 --- /dev/null +++ b/.jenkins/.pipeline/build.js @@ -0,0 +1,5 @@ +'use strict'; +const task = require('./lib/build.js') +const settings = require('./lib/config.js') + +task(Object.assign(settings, { phase: 'build'})) diff --git a/.jenkins/.pipeline/clean.js b/.jenkins/.pipeline/clean.js new file mode 100644 index 000000000..42231d7ff --- /dev/null +++ b/.jenkins/.pipeline/clean.js @@ -0,0 +1,5 @@ +'use strict'; +const settings = require('./lib/config.js') +const task = require('./lib/clean.js') + +task(Object.assign(settings, { phase: settings.options.env})); diff --git a/.jenkins/.pipeline/deploy.js b/.jenkins/.pipeline/deploy.js new file mode 100644 index 000000000..595509459 --- /dev/null +++ b/.jenkins/.pipeline/deploy.js @@ -0,0 +1,5 @@ +'use strict'; +const settings = require('./lib/config.js') +const task = require('./lib/deploy.js') + +task(Object.assign(settings, { phase: settings.options.env})); diff --git a/.jenkins/.pipeline/lib/build.js b/.jenkins/.pipeline/lib/build.js new file mode 100644 index 000000000..529ab21d2 --- /dev/null +++ b/.jenkins/.pipeline/lib/build.js @@ -0,0 +1,36 @@ +'use strict'; +const {OpenShiftClientX} = require('pipeline-cli') +const path = require('path'); + +module.exports = (settings)=>{ + const phases=settings.phases + const options = settings.options + const oc=new OpenShiftClientX(Object.assign({'namespace':phases.build.namespace}, options)); + const phase='build' + var objects = [] + + const templatesLocalBaseUrl =oc.toFileUrl(path.resolve(__dirname, '../../openshift')) + + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/build-master.yaml`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + 'SOURCE_REPOSITORY_URL': oc.git.http_url, + 'SOURCE_REPOSITORY_REF': oc.git.ref + } + })); + + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/build-slave.yaml`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + 'SOURCE_IMAGE_STREAM_TAG': `${phases[phase].name}:${phases[phase].tag}`, + 'SLAVE_NAME':'main' + } + })); + + oc.applyRecommendedLabels(objects, phases[phase].name, phase, phases[phase].changeId, phases[phase].instance) + oc.applyAndBuild(objects) +} \ No newline at end of file diff --git a/.jenkins/.pipeline/lib/clean.js b/.jenkins/.pipeline/lib/clean.js new file mode 100644 index 000000000..643047f20 --- /dev/null +++ b/.jenkins/.pipeline/lib/clean.js @@ -0,0 +1,37 @@ +'use strict'; +const {OpenShiftClientX} = require('pipeline-cli') + +module.exports = (settings)=>{ + const phases = settings.phases + const options = settings.options + const oc=new OpenShiftClientX(Object.assign({'namespace':phases.build.namespace}, options)); + const target_phase=options.env + + for (var k in phases){ + if (phases.hasOwnProperty(k)) { + const phase=phases[k] + if (k == target_phase ){ + //console.log(`phase=${phase}`) + //oc.raw('get', ['bc'], {selector:`app-name=${phase.name},env-id=${phase.changeId},env-name!=prod,!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace, 'output':'custom-columns=kind:.spec.output.to.kind,name:.spec.output.to.name', 'no-headers':'true'}) + let buildConfigs=oc.get('bc', {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace}) + buildConfigs.forEach((bc)=>{ + if (bc.spec.output.to.kind == 'ImageStreamTag'){ + oc.delete([`ImageStreamTag/${bc.spec.output.to.name}`],{'ignore-not-found':'true', 'wait':'true', namespace:phase.namespace}) + } + }) + + let deploymentConfigs=oc.get('dc', {selector:`app=${phase.instance},env-id=${phase.changeId},env-name=${k},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace}) + deploymentConfigs.forEach((dc)=>{ + dc.spec.triggers.forEach((trigger)=>{ + if (trigger.type == 'ImageChange' && trigger.imageChangeParams.from.kind == 'ImageStreamTag'){ + oc.delete([`ImageStreamTag/${trigger.imageChangeParams.from.name}`],{'ignore-not-found':'true', 'wait':'true', namespace:phase.namespace}) + } + }) + }) + + oc.raw('delete', ['all'], {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, wait:'true', namespace:phase.namespace}) + oc.raw('delete', ['pvc,Secret,configmap,endpoints,RoleBinding,role,ServiceAccount,Endpoints'], {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, wait:'true', namespace:phase.namespace}) + } + } + } +} \ No newline at end of file diff --git a/.jenkins/.pipeline/lib/config.js b/.jenkins/.pipeline/lib/config.js new file mode 100644 index 000000000..cf70d83f1 --- /dev/null +++ b/.jenkins/.pipeline/lib/config.js @@ -0,0 +1,19 @@ +'use strict'; +const options= require('pipeline-cli').Util.parseArguments() +const changeId = options.pr //aka pull-request +const version = '1.0.0' +const name = 'nmp-jenkins' + +const phases = { + build: {namespace:'agri-nmp-tools' , name: `${name}`, phase: 'build' , changeId:changeId, suffix: `-build-${changeId}` , instance: `${name}-build-${changeId}` , version:`${version}-${changeId}`, tag:`build-${version}-${changeId}`}, + dev: {namespace:'agri-nmp-tools' , name: `${name}`, phase: 'dev' , changeId:changeId, suffix: `-dev-${changeId}` , instance: `${name}-dev-${changeId}` , version:`${version}-${changeId}`, tag:`dev-${version}-${changeId}`}, + prod: {namespace:'agri-nmp-tools' , name: `${name}`, phase: 'prod' , changeId:changeId, suffix: `` , instance: `${name}` , version:`${version}`, tag:`prod-${version}`}, +}; + +// This callback forces the node process to exit as failure. +process.on('unhandledRejection', (reason) => { + console.log(reason); + process.exit(1); +}); + +module.exports = exports = {phases, options}; \ No newline at end of file diff --git a/.jenkins/.pipeline/lib/deploy.js b/.jenkins/.pipeline/lib/deploy.js new file mode 100644 index 000000000..c5fdccd8f --- /dev/null +++ b/.jenkins/.pipeline/lib/deploy.js @@ -0,0 +1,44 @@ +'use strict'; +const {OpenShiftClientX} = require('pipeline-cli') +const path = require('path'); + +module.exports = (settings)=>{ + const phases = settings.phases + const options = settings.options + const phase=options.env + const changeId = phases[phase].changeId + const oc=new OpenShiftClientX(Object.assign({'namespace':phases[phase].namespace}, options)); + var objects = [] + + const templatesLocalBaseUrl =oc.toFileUrl(path.resolve(__dirname, '../../openshift')) + + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/deploy-master.yaml`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + 'ENV_NAME': phases[phase].phase, + 'ROUTE_HOST': `${phases[phase].name}${phases[phase].suffix}-${phases[phase].namespace}.pathfinder.gov.bc.ca` + } + })) + + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/deploy-slave.yaml`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + 'SLAVE_NAME': 'build', + 'SLAVE_LABELS': 'build deploy test ui-test', + 'SLAVE_EXECUTORS': '3', + 'CPU_REQUEST': '300m', + 'CPU_LIMIT': '500m', + 'MEMORY_REQUEST': '2Gi', + 'MEMORY_LIMIT': '2Gi' + } + })) + + oc.applyRecommendedLabels(objects, phases[phase].name, phase, `${changeId}`, phases[phase].instance) + oc.importImageStreams(objects, phases[phase].tag, phases.build.namespace, phases.build.tag) + oc.applyAndDeploy(objects, phases[phase].instance) + +} \ No newline at end of file diff --git a/.jenkins/.pipeline/npmw b/.jenkins/.pipeline/npmw new file mode 100644 index 000000000..1eed7c953 --- /dev/null +++ b/.jenkins/.pipeline/npmw @@ -0,0 +1,12 @@ +#!/bin/sh +set +x +type -t nvm && nvm deactivate +export NVM_DIR="$(git rev-parse --show-toplevel)/.nvm" +if [ ! -f "$NVM_DIR/nvm.sh" ]; then + mkdir -p "${NVM_DIR}" + curl -sSL -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash &>/dev/null +fi +source "$NVM_DIR/nvm.sh" &>/dev/null +METHOD=script nvm install --no-progress &>/dev/null +nvm use &>/dev/null +exec npm "$@" diff --git a/.jenkins/.pipeline/package-lock.json b/.jenkins/.pipeline/package-lock.json new file mode 100644 index 000000000..0428b38ac --- /dev/null +++ b/.jenkins/.pipeline/package-lock.json @@ -0,0 +1,46 @@ +{ + "name": "pipeline", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "pipeline-cli": { + "version": "git+https://github.com/BCDevOps/pipeline-cli.git#0d81b886aa753eacbb2bc254b5dc869ffb2c5fce", + "from": "git+https://github.com/BCDevOps/pipeline-cli.git#v1.1", + "requires": { + "debug": "^4.1.0", + "lodash.isfunction": "^3.0.9", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1" + } + } + } +} diff --git a/.jenkins/.pipeline/package.json b/.jenkins/.pipeline/package.json new file mode 100644 index 000000000..0ca51bbfc --- /dev/null +++ b/.jenkins/.pipeline/package.json @@ -0,0 +1,23 @@ +{ + "name": "pipeline", + "version": "1.0.0", + "description": "This a pipeliene script", + "engines": { + "node": ">=8" + }, + "scripts": { + "build": "node build.js", + "clean": "node clean.js", + "deploy": "node deploy.js", + "version": "echo \"node@$(node --version) ($(which node))\" && echo \"npm@$(npm --version) ($(which npm))\" && npm ls" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bcgov/ocp-sso.git" + }, + "author": "", + "license": "Apache-2.0", + "dependencies": { + "pipeline-cli": "git+https://github.com/BCDevOps/pipeline-cli.git#v1.1" + } +} diff --git a/.jenkins/Jenkinsfile b/.jenkins/Jenkinsfile new file mode 100644 index 000000000..3b1d8233d --- /dev/null +++ b/.jenkins/Jenkinsfile @@ -0,0 +1,57 @@ +pipeline { + agent none + options { + disableResume() + } + stages { + stage('Build') { + agent { label 'build' } + steps { + script { + def filesInThisCommitAsString = sh(script:"git diff --name-only HEAD~1..HEAD | grep '^.jenkins/' || echo -n ''", returnStatus: false, returnStdout: true).trim() + def hasChangesInPath = (filesInThisCommitAsString.length() > 0) + echo "${filesInThisCommitAsString}" + if (!currentBuild.rawBuild.getCauses()[0].toString().contains('UserIdCause') && !hasChangesInPath){ + currentBuild.rawBuild.delete() + error("No changes detected in the path ('^.jenkins/')") + } + } + echo "Aborting all running jobs ..." + script { + abortAllPreviousBuildInProgress(currentBuild) + } + echo "BRANCH_NAME:${env.BRANCH_NAME}\nCHANGE_ID:${env.CHANGE_ID}\nCHANGE_TARGET:${env.CHANGE_TARGET}" + echo "Building ..." + sh "cd .jenkins/.pipeline && ./npmw ci && ./npmw run build -- --pr=${CHANGE_ID}" + } + } + stage('Deploy (DEV)') { + agent { label 'deploy' } + steps { + echo "Deploying ..." + sh "cd .jenkins/.pipeline && ./npmw ci && DEBUG=info* ./npmw run deploy -- --pr=${CHANGE_ID} --env=dev" + } + } + stage('Deploy (PROD)') { + agent { label 'deploy' } + input { + message "Should we continue with deployment to PROD?" + ok "Yes!" + } + steps { + echo "Deploying ..." + sh "cd .jenkins/.pipeline && ./npmw ci && ./npmw run deploy -- --pr=${CHANGE_ID} --env=prod" + } + } + stage('Acceptance') { + agent { label 'deploy' } + input { + message "Should we continue with cleanup?" + ok "Yes!" + } + steps { + echo "Cleaning ..." + } + } + } +} \ No newline at end of file diff --git a/.jenkins/README.md b/.jenkins/README.md new file mode 100644 index 000000000..f1d572cff --- /dev/null +++ b/.jenkins/README.md @@ -0,0 +1,40 @@ +# Overview + +For running locally, it is recommended to use locally installed npm/node. The command snippets provide bellow assume you have npm/node installed. Also, the command lines are provided as subshell (within parthnesis) so that it will work regardless of of your current shell work directory, as long as it is within the git working directory. + +For running from a Jenkinsfile, it is recommened to replace `npm` with the provided `npmw` as it will download and install node/npm using `nvm`. + +Before running in any of your projects ensure that you have created proper GitHub and Slave User secrets below: +template.-github +template.-slave-user + +Github Webhooks are only created during the PROD deployment. + +Windows users can just do the `cd` manually to the root folder of their repo and remove `$(git rev-parse --show-toplevel)/` from the commands below. + +# Build +``` +( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run build -- --pr=0 --dev-mode=true ) +``` +Where: +`--pr=0` is used to set the pull request number to build from. +`--dev-mode=true` is used to indicate that the build will actually take the files in the current working directory, as opposed to a fresh `git clone` + +# Deploy to DEV +``` +( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run deploy -- --pr=0 --env=dev ) +``` + +# Deploy to PROD +``` +( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run deploy -- --pr=0 --env=prod ) +``` + +# Clean +The clean script can run against each persistent environment, starting from `build`. +``` +( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run clean -- --pr=0 --env=build ) +( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run clean -- --pr=0 --env=dev ) +``` + +*Warning*: Do *NOT* run against `test` or `prod`. It will cause *PERMANENT* deletion of all objects including `PVC`! be warned! diff --git a/.jenkins/docker/Dockerfile b/.jenkins/docker/Dockerfile new file mode 100644 index 000000000..1eec80a27 --- /dev/null +++ b/.jenkins/docker/Dockerfile @@ -0,0 +1,11 @@ +FROM jenkins/core/there + +USER 0 +COPY ./contrib/jenkins/configuration $JENKINS_REF_HOME + +RUN set -x && \ + chgrp -R 0 $JENKINS_REF_HOME && \ + chmod -R 644 $JENKINS_REF_HOME && \ + chmod -R g+rwX $JENKINS_REF_HOME + +USER 1001 diff --git a/.jenkins/docker/contrib/jenkins/configuration/jobs/_jenkins/config.xml b/.jenkins/docker/contrib/jenkins/configuration/jobs/_jenkins/config.xml new file mode 100644 index 000000000..3d88b55e6 --- /dev/null +++ b/.jenkins/docker/contrib/jenkins/configuration/jobs/_jenkins/config.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + false + + + + + + + true + -1 + -1 + + + false + + + + + a4d8b211-33bd-4df5-a7cb-2194019d1e28 + github-account + bcgov + agri-nmp + + + 2 + + + + 2 + + + + + + + + + + + + + + + + + + .jenkins/Jenkinsfile + + \ No newline at end of file diff --git a/.jenkins/docker/contrib/jenkins/configuration/jobs/nmp/config.xml b/.jenkins/docker/contrib/jenkins/configuration/jobs/nmp/config.xml new file mode 100644 index 000000000..d71e02a66 --- /dev/null +++ b/.jenkins/docker/contrib/jenkins/configuration/jobs/nmp/config.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + false + + + + + + + true + -1 + -1 + + + false + + + + + c24e5b83-d86e-49d1-ad31-1d8479daf2c9 + github-account + bcgov + agri-nmp + + + 2 + + + + 2 + + + + + + + + + + + + + + + + + + Jenkinsfile + + \ No newline at end of file diff --git a/.jenkins/openshift/build-master.yaml b/.jenkins/openshift/build-master.yaml new file mode 100644 index 000000000..83ee1e4ce --- /dev/null +++ b/.jenkins/openshift/build-master.yaml @@ -0,0 +1,81 @@ +apiVersion: template.openshift.io/v1 +kind: Template +metadata: + creationTimestamp: null + name: jenkins +objects: +- apiVersion: v1 + kind: ImageStream + metadata: + creationTimestamp: null + labels: + shared: "true" + name: ${NAME} + spec: + lookupPolicy: + local: false +- apiVersion: v1 + kind: BuildConfig + metadata: + creationTimestamp: null + name: ${NAME}${SUFFIX} + spec: + failedBuildsHistoryLimit: 2 + output: + to: + kind: ImageStreamTag + name: ${NAME}:${VERSION} + postCommit: {} + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: "1" + memory: 1Gi + runPolicy: SerialLatestOnly + source: + contextDir: .jenkins/docker + git: + ref: ${SOURCE_REPOSITORY_REF} + uri: ${SOURCE_REPOSITORY_URL} + type: Git + strategy: + dockerStrategy: + from: + kind: ImageStreamTag + name: ${SOURCE_IMAGE_STREAM_TAG} + namespace: ${SOURCE_IMAGE_STREAM_NAMESPACE} + type: Docker + successfulBuildsHistoryLimit: 2 + triggers: + - type: ConfigChange + - imageChange: {} + type: ImageChange +parameters: +- description: A name used for all objects + displayName: Name + name: NAME + required: true + value: jenkins +- description: A name suffix used for all objects + displayName: Suffix + name: SUFFIX + required: false + value: "" +- description: A version used for the image tags + displayName: version + name: VERSION + required: true + value: v1.0.0 +- name: SOURCE_IMAGE_STREAM_NAMESPACE + required: true + value: bcgov +- name: SOURCE_IMAGE_STREAM_TAG + required: true + value: jenkins-basic:v2-latest +- name: SOURCE_REPOSITORY_URL + required: true +- name: SOURCE_REPOSITORY_REF + required: false + value: tools diff --git a/.jenkins/openshift/build-slave.yaml b/.jenkins/openshift/build-slave.yaml new file mode 100644 index 000000000..984fedc42 --- /dev/null +++ b/.jenkins/openshift/build-slave.yaml @@ -0,0 +1,110 @@ +apiVersion: template.openshift.io/v1 +kind: Template +metadata: + creationTimestamp: null + name: jenkins +objects: +- apiVersion: v1 + kind: ImageStream + metadata: + creationTimestamp: null + labels: + shared: "true" + name: ${NAME}-slave-${SLAVE_NAME} + spec: + lookupPolicy: + local: false +- apiVersion: v1 + kind: BuildConfig + metadata: + creationTimestamp: null + name: ${NAME}-slave-${SLAVE_NAME}${SUFFIX} + spec: + failedBuildsHistoryLimit: 2 + output: + to: + kind: ImageStreamTag + name: ${NAME}-slave-${SLAVE_NAME}:${VERSION} + postCommit: {} + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: "1" + memory: 1Gi + runPolicy: SerialLatestOnly + source: +# contextDir: ${SOURCE_CONTEXT_DIR} +# git: +# ref: ${SOURCE_GIT_REF} +# uri: ${SOURCE_GIT_URL} +# type: Git + dockerfile: | + FROM BuildConfig + USER 0 + RUN fix_permission(){ while [[ $# > 0 ]] ; do chgrp -R 0 "$1" && chmod -R g=u "$1"; shift; done } && \ + set -x && \ + mkdir /opt/flywaydb && \ + curl -sSL https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/5.2.4/flyway-commandline-5.2.4-linux-x64.tar.gz | tar xvz --strip-components=1 -C /opt/flywaydb && \ + ln -s /opt/flywaydb/flyway /usr/local/bin && \ + mkdir /opt/liquibase && \ + curl -sSL https://github.com/liquibase/liquibase/releases/download/liquibase-parent-3.6.3/liquibase-3.6.3-bin.tar.gz | tar xvz -C /opt/liquibase --exclude=sdk --exclude=liquibase.bat && \ + ln -s /opt/liquibase/liquibase /usr/local/bin && \ + curl -sSL -o /tmp/sonnar-scanner-cli.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.3.0.1492-linux.zip && \ + unzip /tmp/sonnar-scanner-cli.zip -d /tmp/sonnar-scanner-cli && \ + mv /tmp/sonnar-scanner-cli/sonar-scanner-3.3.0.1492-linux /opt/sonnar-scanner && \ + ln -s /opt/sonnar-scanner/bin/sonar-scanner /usr/local/bin && \ + rm -rf /tmp/sonnar-scanner-cli.zip && \ + rm -rf /tmp/sonnar-scanner-cli && \ + fix_permission '/opt/flywaydb' '/opt/liquibase' '/opt/sonnar-scanner' + USER 1001 + type: Dockerfile + strategy: + dockerStrategy: + from: + kind: ImageStreamTag + name: ${SOURCE_IMAGE_STREAM_TAG} + namespace: ${SOURCE_IMAGE_STREAM_NAMESPACE} + type: Docker + successfulBuildsHistoryLimit: 2 + triggers: + - type: ConfigChange + - imageChange: + from: + kind: ImageStreamTag + name: ${SOURCE_IMAGE_STREAM_TAG} + namespace: ${SOURCE_IMAGE_STREAM_NAMESPACE} + type: ImageChange +parameters: +- description: A name used for all objects + displayName: Name + name: NAME + required: true + value: jenkins +- description: A name suffix used for all objects + displayName: Suffix + name: SUFFIX + required: false + value: "-0" +- description: A version used for the image tags + displayName: version + name: VERSION + required: true + value: latest +- name: SLAVE_NAME + value: build +- name: SOURCE_IMAGE_STREAM_NAMESPACE + value: "" +- name: SOURCE_IMAGE_STREAM_TAG + required: true + value: "jenkins:build-v2.0-0" +- name: SOURCE_GIT_URL + required: true + value: https://github.com/cvarjao-o/hello-world.git +- name: SOURCE_GIT_REF + required: true + value: master +- name: SOURCE_CONTEXT_DIR + required: true + value: .jenkins/docker-slave \ No newline at end of file diff --git a/.jenkins/openshift/deploy-master.yaml b/.jenkins/openshift/deploy-master.yaml new file mode 100644 index 000000000..1cefcb635 --- /dev/null +++ b/.jenkins/openshift/deploy-master.yaml @@ -0,0 +1,297 @@ +apiVersion: template.openshift.io/v1 +kind: Template +metadata: + creationTimestamp: null + name: jenkins +objects: +- apiVersion: v1 + kind: ImageStream + metadata: + creationTimestamp: null + labels: + shared: "true" + name: ${NAME} + spec: + lookupPolicy: + local: false +- apiVersion: v1 + kind: Secret + metadata: + annotations: + as-copy-of: template.${NAME}-slave-user + as-copy-of/preserve: password + name: ${NAME}${SUFFIX}-slave-user + stringData: + metadata.name: ${NAME}${SUFFIX}-slave-user + password: ${SLAVE_USER_PASSWORD} + username: jenkins-slave + type: kubernetes.io/basic-auth +- apiVersion: v1 + kind: Secret + metadata: + annotations: + as-copy-of: template.${NAME}-github + name: ${NAME}${SUFFIX}-github + stringData: + metadata.name: ${NAME}${SUFFIX}-github + password: ${GITHUB_TOKEN} + username: ${GITHUB_USERNAME} + type: kubernetes.io/basic-auth +- apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + annotations: + volume.beta.kubernetes.io/storage-class: gluster-file + volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/glusterfs + name: ${NAME}${SUFFIX} + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +- apiVersion: v1 + kind: ServiceAccount + metadata: + annotations: + serviceaccounts.openshift.io/oauth-redirectreference.jenkins: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"${NAME}${SUFFIX}"}}' + name: ${NAME}${SUFFIX} +- apiVersion: v1 + groupNames: null + kind: RoleBinding + metadata: + name: ${NAME}${SUFFIX}_edit + roleRef: + name: edit + subjects: + - kind: ServiceAccount + name: ${NAME}${SUFFIX} +- apiVersion: v1 + groupNames: null + kind: RoleBinding + metadata: + name: ${NAME}${SUFFIX}_admin + roleRef: + name: admin + subjects: + - kind: ServiceAccount + name: ${NAME}${SUFFIX} +- apiVersion: v1 + kind: DeploymentConfig + metadata: + annotations: + template.alpha.openshift.io/wait-for-ready: "true" + creationTimestamp: null + name: ${NAME}${SUFFIX} + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + deploymentconfig: ${NAME}${SUFFIX} + strategy: + activeDeadlineSeconds: 21600 + recreateParams: + timeoutSeconds: 600 + resources: {} + type: Recreate + template: + metadata: + creationTimestamp: null + labels: + deploymentconfig: ${NAME}${SUFFIX} + spec: + containers: + - command: + - /usr/local/bin/container-entrypoint + - /usr/local/bin/jenkins-run + env: + - name: USE_JAVA_DIAGNOSTICS + value: "true" + - name: JENKINS_URL + value: https://${ROUTE_HOST}${ROUTE_PATH} + - name: ENV_NAME + value: ${ENV_NAME} + - name: ENV_ID + value: ${ENV_ID} + image: ' ' + imagePullPolicy: Always + livenessProbe: + failureThreshold: 3 + httpGet: + path: /login + port: 8080 + initialDelaySeconds: 420 + periodSeconds: 360 + timeoutSeconds: 240 + name: jenkins + ports: + - containerPort: 50000 + protocol: TCP + - containerPort: 8080 + protocol: TCP + readinessProbe: + httpGet: + path: /login + port: 8080 + initialDelaySeconds: 3 + timeoutSeconds: 240 + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 300m + memory: 2Gi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /var/lib/jenkins/jobs + name: jenkins-jobs + readOnly: false + - mountPath: /var/run/pod + name: pod-metadata + - mountPath: /run/secrets/jenkins-slave-user + name: jenkins-slave-user + readOnly: true + - mountPath: /run/secrets/github + name: github + readOnly: true + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccount: ${NAME}${SUFFIX} + serviceAccountName: ${NAME}${SUFFIX} + terminationGracePeriodSeconds: 30 + volumes: + - name: jenkins-jobs + persistentVolumeClaim: + claimName: ${NAME}${SUFFIX} + - downwardAPI: + items: + - fieldRef: + fieldPath: metadata.name + name: name + path: name + - fieldRef: + fieldPath: metadata.namespace + name: namespace + path: namespace + - fieldRef: + fieldPath: metadata.labels + name: labels + path: labels + - fieldRef: + fieldPath: metadata.annotations + name: annotations + path: annotations + name: pod-metadata + - name: jenkins-slave-user + secret: + defaultMode: 420 + secretName: ${NAME}${SUFFIX}-slave-user + - name: github + secret: + defaultMode: 420 + secretName: ${NAME}${SUFFIX}-github + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - jenkins + from: + kind: ImageStreamTag + name: ${NAME}:${VERSION} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + creationTimestamp: null + name: ${NAME}${SUFFIX} + spec: + ports: + - name: 8080-tcp + port: 8080 + protocol: TCP + targetPort: 8080 + - name: 50000-tcp + port: 50000 + protocol: TCP + targetPort: 50000 + selector: + deploymentconfig: ${NAME}${SUFFIX} + sessionAffinity: None + type: ClusterIP +- apiVersion: v1 + kind: Route + metadata: + creationTimestamp: null + name: ${NAME}${SUFFIX} + spec: + host: ${ROUTE_HOST} + path: ${ROUTE_PATH} + port: + targetPort: 8080-tcp + tls: + termination: edge + to: + kind: Service + name: ${NAME}${SUFFIX} + weight: 100 + wildcardPolicy: None +parameters: +- description: A name used for all objects + displayName: Name + name: NAME + required: true +- description: A name suffix used for all objects + displayName: Suffix + name: SUFFIX + required: false + value: "" +- description: A version used for the image tags + displayName: version + name: VERSION + required: true + value: v1.0.0 +- description: GITHUB_USERNAME + displayName: GITHUB_USERNAME + name: GITHUB_USERNAME + required: true + value: cvarjao +- description: ROUTE_HOST + displayName: ROUTE_HOST + name: ROUTE_HOST + required: true +- description: ROUTE_PATH + displayName: ROUTE_PATH + name: ROUTE_PATH + required: true + value: / +- description: Environment Name + displayName: ENV_NAME + name: ENV_NAME + required: true + value: prod +- description: Environment ID + displayName: ENV_ID + name: ENV_ID + required: true + value: prod +- description: SLAVE_USER_PASSWORD + displayName: SLAVE_USER_PASSWORD + from: '[a-zA-Z0-9]{16}' + generate: expression + name: SLAVE_USER_PASSWORD +- description: GITHUB_USERNAME + displayName: GITHUB_USERNAME + name: GITHUB_USERNAME + required: false + value: "" +- description: GitHub Personal Access Token + displayName: GITHUB_USERNAME + name: GITHUB_TOKEN + required: false + value: "" diff --git a/.jenkins/openshift/deploy-prereq.yaml b/.jenkins/openshift/deploy-prereq.yaml new file mode 100644 index 000000000..8ac749f4e --- /dev/null +++ b/.jenkins/openshift/deploy-prereq.yaml @@ -0,0 +1,31 @@ +apiVersion: template.openshift.io/v1 +kind: Template +objects: +- apiVersion: v1 + kind: Secret + metadata: + annotations: null + name: template.${NAME}-slave-user + stringData: + metadata.name: template.${NAME}-slave-user + username: jenkins-slave +- apiVersion: v1 + kind: Secret + metadata: + annotations: null + name: template.${NAME}-github + stringData: + metadata.name: template.${NAME}-github + username: ${GH_USERNAME} + password: ${GH_ACCESS_TOKEN} +parameters: +- description: A name used for all objects + displayName: Name + name: NAME + required: true + value: jenkins +- name: GH_USERNAME + required: true +- description: GitHub Personal Access Token + name: GH_ACCESS_TOKEN + required: true diff --git a/.jenkins/openshift/deploy-slave.yaml b/.jenkins/openshift/deploy-slave.yaml new file mode 100644 index 000000000..6f992b259 --- /dev/null +++ b/.jenkins/openshift/deploy-slave.yaml @@ -0,0 +1,164 @@ +apiVersion: template.openshift.io/v1 +kind: Template +metadata: + creationTimestamp: null + name: jenkins +objects: +- apiVersion: v1 + kind: DeploymentConfig + metadata: + creationTimestamp: null + name: ${NAME}-${SLAVE_NAME}${SUFFIX} + spec: + replicas: "${{REPLICAS}}" + revisionHistoryLimit: 10 + selector: + deploymentconfig: ${NAME}-${SLAVE_NAME}${SUFFIX} + strategy: + activeDeadlineSeconds: 21600 + recreateParams: + timeoutSeconds: 600 + resources: {} + type: Recreate + template: + metadata: + creationTimestamp: null + labels: + deploymentconfig: ${NAME}-${SLAVE_NAME}${SUFFIX} + spec: + initContainers: + - name: init + image: " " + command: + - "curl" + - "-sSf" + - "http://${NAME}${SUFFIX}:8080/login" + containers: + - command: + - bash + - -c + - cd $HOME && java -XshowSettings:vm -version && exec java -jar /usr/lib/jenkins/swarm-client.jar + -name "$(cat /etc/hostname)" -deleteExistingClients -fsroot "$JENKINS_HOME/$(cat + /etc/hostname)" -master http://$JENKINS_MASTER_SERVICE:8080 -disableSslVerification + -username "$(cat /var/run/secrets/jenkins-slave-user/username)" -passwordFile + /var/run/secrets/jenkins-slave-user/password -description "$(cat /etc/hostname)" + -executors ${SLAVE_EXECUTORS} -labels '${SLAVE_LABELS}' -mode + 'normal' -retry 10 -tunnel $JENKINS_MASTER_SERVICE:50000 -disableClientsUniqueId + env: + - name: JENKINS_MASTER_SERVICE + value: ${NAME}${SUFFIX} + - name: JAVA_TOOL_OPTIONS + value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap + -XX:MaxRAMFraction=5 -XX:MaxHeapFreeRatio=20 -XX:MinHeapFreeRatio=10 + -XX:+UseParallelGC -XX:ParallelGCThreads=2 + - name: ENV_NAME + value: ${ENV_NAME} + - name: ENV_ID + value: ${ENV_ID} + image: ' ' + imagePullPolicy: Always + name: jenkins + ports: + - containerPort: 50000 + protocol: TCP + - containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: ${CPU_LIMIT} + memory: ${MEMORY_LIMIT} + requests: + cpu: ${CPU_REQUEST} + memory: ${MEMORY_REQUEST} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /var/run/pod + name: pod-metadata + - mountPath: /run/secrets/jenkins-slave-user + name: jenkins-slave-user + readOnly: true + - mountPath: /run/secrets/github + name: github + readOnly: true + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccount: ${NAME}${SUFFIX} + serviceAccountName: ${NAME}${SUFFIX} + terminationGracePeriodSeconds: 30 + volumes: + - name: jenkins-home + persistentVolumeClaim: + claimName: ${NAME}${SUFFIX} + - downwardAPI: + items: + - fieldRef: + fieldPath: metadata.name + name: name + path: name + - fieldRef: + fieldPath: metadata.namespace + name: namespace + path: namespace + - fieldRef: + fieldPath: metadata.labels + name: labels + path: labels + - fieldRef: + fieldPath: metadata.annotations + name: annotations + path: annotations + name: pod-metadata + - name: jenkins-slave-user + secret: + defaultMode: 420 + secretName: ${NAME}${SUFFIX}-slave-user + - name: github + secret: + defaultMode: 420 + secretName: ${NAME}${SUFFIX}-github + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - jenkins + - init + from: + kind: ImageStreamTag + name: ${NAME}:${VERSION} + type: ImageChange + - type: ConfigChange +parameters: +- description: A name used for all objects + displayName: Name + name: NAME + required: true +- description: A name suffix used for all objects + displayName: Suffix + name: SUFFIX + required: false + value: "" +- description: A version used for the image tags + displayName: version + name: VERSION + required: true + value: v1.0.0 +- name: SLAVE_NAME + required: true +- name: SLAVE_LABELS + value: "Linux rhel rhel7 build test deploy light" +- name: SLAVE_EXECUTORS + value: "3" +- name: REPLICAS + value: "1" +- name: CPU_REQUEST + value: "300m" +- name: CPU_LIMIT + value: "500m" +- name: MEMORY_REQUEST + value: "1Gi" +- name: MEMORY_LIMIT + value: "1Gi" \ No newline at end of file diff --git a/.jenkins/openshift/secrets.json b/.jenkins/openshift/secrets.json new file mode 100644 index 000000000..1add567d0 --- /dev/null +++ b/.jenkins/openshift/secrets.json @@ -0,0 +1,50 @@ +{ + "kind": "Template", + "apiVersion": "v1", + "metadata": { + "name": "jenkins", + "creationTimestamp": null + }, + "parameters":[ + { + "name": "NAME", + "displayName": "Name", + "description": "A name used for all objects", + "required": true, + "value": "jenkins" + },{ + "name": "GH_USERNAME", + "required": true + },{ + "name": "GH_PASSWORD", + "description": "GitHub Personal Access Token", + "required": true + } + ], + "objects": [ + { + "apiVersion": "v1", + "kind": "Secret", + "metadata": { + "annotations": null, + "name": "template.${NAME}-slave-user" + }, + "stringData": { + "metadata.name": "template.${NAME}-slave-user", + "username": "jenkins-slave" + } + },{ + "apiVersion": "v1", + "kind": "Secret", + "metadata": { + "annotations": null, + "name": "template.${NAME}-github" + }, + "stringData": { + "metadata.name": "template.${NAME}-github", + "username": "${GH_USERNAME}", + "password": "${GH_PASSWORD}" + } + } + ] +} \ No newline at end of file diff --git a/.pipeline/.nvmrc b/.pipeline/.nvmrc new file mode 100644 index 000000000..6b12bc745 --- /dev/null +++ b/.pipeline/.nvmrc @@ -0,0 +1 @@ +v10.15.2 \ No newline at end of file diff --git a/.pipeline/build.js b/.pipeline/build.js new file mode 100644 index 000000000..3ac899f86 --- /dev/null +++ b/.pipeline/build.js @@ -0,0 +1,5 @@ +'use strict'; +const task = require('./lib/build.js') +const settings = require('./lib/config.js') + +task(Object.assign(settings, { phase: 'build'})) diff --git a/.pipeline/clean.js b/.pipeline/clean.js new file mode 100644 index 000000000..42231d7ff --- /dev/null +++ b/.pipeline/clean.js @@ -0,0 +1,5 @@ +'use strict'; +const settings = require('./lib/config.js') +const task = require('./lib/clean.js') + +task(Object.assign(settings, { phase: settings.options.env})); diff --git a/.pipeline/deploy.js b/.pipeline/deploy.js new file mode 100644 index 000000000..595509459 --- /dev/null +++ b/.pipeline/deploy.js @@ -0,0 +1,5 @@ +'use strict'; +const settings = require('./lib/config.js') +const task = require('./lib/deploy.js') + +task(Object.assign(settings, { phase: settings.options.env})); diff --git a/.pipeline/lib/build.js b/.pipeline/lib/build.js new file mode 100644 index 000000000..578e7790f --- /dev/null +++ b/.pipeline/lib/build.js @@ -0,0 +1,43 @@ +'use strict'; +const {OpenShiftClientX} = require('pipeline-cli') +const path = require('path'); + +module.exports = (settings)=>{ + const phases = settings.phases + const options = settings.options + const phase='build' + const oc=new OpenShiftClientX(Object.assign({'namespace':phases.build.namespace}, options)); + const objects = [] + const templatesLocalBaseUrl =oc.toFileUrl(path.resolve(__dirname, '../../OpenShift')) + + // The building of your cool app goes here ▼▼▼ + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/dotnet-21.bc.json`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + } + })); + + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/dotnet-21-node.bc.json`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + 'SOURCE_REPOSITORY_URL': oc.git.http_url, + 'GIT_REF': oc.git.ref + } + })); + + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/nmp.bc.json`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + 'SOURCE_REPOSITORY_URL': oc.git.http_url, + 'GIT_REF': oc.git.ref + } + })); + oc.applyRecommendedLabels(objects, phases[phase].name, phase, phases[phase].changeId, phases[phase].instance) + oc.applyAndBuild(objects) +} \ No newline at end of file diff --git a/.pipeline/lib/clean.js b/.pipeline/lib/clean.js new file mode 100644 index 000000000..643047f20 --- /dev/null +++ b/.pipeline/lib/clean.js @@ -0,0 +1,37 @@ +'use strict'; +const {OpenShiftClientX} = require('pipeline-cli') + +module.exports = (settings)=>{ + const phases = settings.phases + const options = settings.options + const oc=new OpenShiftClientX(Object.assign({'namespace':phases.build.namespace}, options)); + const target_phase=options.env + + for (var k in phases){ + if (phases.hasOwnProperty(k)) { + const phase=phases[k] + if (k == target_phase ){ + //console.log(`phase=${phase}`) + //oc.raw('get', ['bc'], {selector:`app-name=${phase.name},env-id=${phase.changeId},env-name!=prod,!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace, 'output':'custom-columns=kind:.spec.output.to.kind,name:.spec.output.to.name', 'no-headers':'true'}) + let buildConfigs=oc.get('bc', {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace}) + buildConfigs.forEach((bc)=>{ + if (bc.spec.output.to.kind == 'ImageStreamTag'){ + oc.delete([`ImageStreamTag/${bc.spec.output.to.name}`],{'ignore-not-found':'true', 'wait':'true', namespace:phase.namespace}) + } + }) + + let deploymentConfigs=oc.get('dc', {selector:`app=${phase.instance},env-id=${phase.changeId},env-name=${k},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace}) + deploymentConfigs.forEach((dc)=>{ + dc.spec.triggers.forEach((trigger)=>{ + if (trigger.type == 'ImageChange' && trigger.imageChangeParams.from.kind == 'ImageStreamTag'){ + oc.delete([`ImageStreamTag/${trigger.imageChangeParams.from.name}`],{'ignore-not-found':'true', 'wait':'true', namespace:phase.namespace}) + } + }) + }) + + oc.raw('delete', ['all'], {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, wait:'true', namespace:phase.namespace}) + oc.raw('delete', ['pvc,Secret,configmap,endpoints,RoleBinding,role,ServiceAccount,Endpoints'], {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, wait:'true', namespace:phase.namespace}) + } + } + } +} \ No newline at end of file diff --git a/.pipeline/lib/config.js b/.pipeline/lib/config.js new file mode 100644 index 000000000..5088aa51c --- /dev/null +++ b/.pipeline/lib/config.js @@ -0,0 +1,20 @@ +'use strict'; +const options= require('pipeline-cli').Util.parseArguments() +const changeId = options.pr //aka pull-request +const version = '1.0.0' +const name = 'nmp' + +const phases = { + build: {namespace:'agri-nmp-tools', name: `${name}`, phase: 'build', changeId:changeId, suffix: `-build-${changeId}`, instance: `${name}-build-${changeId}`, version:`${version}-${changeId}`, tag:`build-${version}-${changeId}`, nmpreplicas:'1', pdfreplicas:'1' , host:`${name}-pr-${changeId}-agri-nmp-tools.pathfinder.gov.bc.ca`}, + dev: {namespace:'agri-nmp-dev' , name: `${name}`, phase: 'dev' , changeId:changeId, suffix: `-dev-${changeId}` , instance: `${name}-dev-${changeId}` , version:`${version}-${changeId}`, tag:`dev-${version}-${changeId}` , nmpreplicas:'1', pdfreplicas:'1' , host:`${name}-pr-${changeId}-agri-nmp-dev.pathfinder.gov.bc.ca`}, + test: {namespace:'agri-nmp-test' , name: `${name}`, phase: 'test' , changeId:changeId, suffix: `-test` , instance: `${name}-test` , version:`${version}-${changeId}`, tag:`test-${version}` , nmpreplicas:'2', pdfreplicas:'2' , host:`${name}-test-agri-nmp-test.pathfinder.gov.bc.ca`}, + prod: {namespace:'agri-nmp-prod' , name: `${name}`, phase: 'prod' , changeId:changeId, suffix: `-prod` , instance: `${name}-prod` , version:`${version}-${changeId}`, tag:`prod-${version}` , nmpreplicas:'3', pdfreplicas:'3' , host:'nmp.apps.nrs.gov.bc.ca'} +}; + +// This callback forces the node process to exit as failure. +process.on('unhandledRejection', (reason) => { + console.log(reason); + process.exit(1); +}); + +module.exports = exports = {phases, options}; \ No newline at end of file diff --git a/.pipeline/lib/deploy.js b/.pipeline/lib/deploy.js new file mode 100644 index 000000000..b938e9ea7 --- /dev/null +++ b/.pipeline/lib/deploy.js @@ -0,0 +1,35 @@ +'use strict'; +const {OpenShiftClientX} = require('pipeline-cli') +const path = require('path'); + +module.exports = (settings)=>{ + const phases = settings.phases + const options= settings.options + const phase=options.env + const oc=new OpenShiftClientX(Object.assign({'namespace':phases[phase].namespace}, options)); + const templatesLocalBaseUrl =oc.toFileUrl(path.resolve(__dirname, '../../OpenShift')) + var objects = [] + + // The deployment of your cool app goes here ▼▼▼ + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/postgresql.dc.json`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix + } + })); + + objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/nmp.dc.json`, { + 'param':{ + 'NAME': phases[phase].name, + 'SUFFIX': phases[phase].suffix, + 'VERSION': phases[phase].tag, + 'HOST': phases[phase].host, + 'NMP_REPLICAS': phases[phase].nmpreplicas, + 'PDF_REPLICAS': phases[phase].pdfreplicas + } + })); + + oc.applyRecommendedLabels(objects, phases[phase].name, phase, phases[phase].changeId, phases[phase].instance) + oc.importImageStreams(objects, phases[phase].tag, phases.build.namespace, phases.build.tag) + oc.applyAndDeploy(objects, phases[phase].instance) +} diff --git a/.pipeline/npmw b/.pipeline/npmw new file mode 100644 index 000000000..1eed7c953 --- /dev/null +++ b/.pipeline/npmw @@ -0,0 +1,12 @@ +#!/bin/sh +set +x +type -t nvm && nvm deactivate +export NVM_DIR="$(git rev-parse --show-toplevel)/.nvm" +if [ ! -f "$NVM_DIR/nvm.sh" ]; then + mkdir -p "${NVM_DIR}" + curl -sSL -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash &>/dev/null +fi +source "$NVM_DIR/nvm.sh" &>/dev/null +METHOD=script nvm install --no-progress &>/dev/null +nvm use &>/dev/null +exec npm "$@" diff --git a/.pipeline/package-lock.json b/.pipeline/package-lock.json new file mode 100644 index 000000000..0428b38ac --- /dev/null +++ b/.pipeline/package-lock.json @@ -0,0 +1,46 @@ +{ + "name": "pipeline", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "pipeline-cli": { + "version": "git+https://github.com/BCDevOps/pipeline-cli.git#0d81b886aa753eacbb2bc254b5dc869ffb2c5fce", + "from": "git+https://github.com/BCDevOps/pipeline-cli.git#v1.1", + "requires": { + "debug": "^4.1.0", + "lodash.isfunction": "^3.0.9", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1" + } + } + } +} diff --git a/.pipeline/package.json b/.pipeline/package.json new file mode 100644 index 000000000..0ca51bbfc --- /dev/null +++ b/.pipeline/package.json @@ -0,0 +1,23 @@ +{ + "name": "pipeline", + "version": "1.0.0", + "description": "This a pipeliene script", + "engines": { + "node": ">=8" + }, + "scripts": { + "build": "node build.js", + "clean": "node clean.js", + "deploy": "node deploy.js", + "version": "echo \"node@$(node --version) ($(which node))\" && echo \"npm@$(npm --version) ($(which npm))\" && npm ls" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bcgov/ocp-sso.git" + }, + "author": "", + "license": "Apache-2.0", + "dependencies": { + "pipeline-cli": "git+https://github.com/BCDevOps/pipeline-cli.git#v1.1" + } +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..1a6a387a8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,48 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "build", + "cwd":"${workspaceFolder}/.pipeline", + "program": "${workspaceFolder}/.pipeline/build.js", + "env": {"DEBUG":"*"}, + "args": ["--pr=0","--dev-mode=true"], + "console": "integratedTerminal" + }, + { + "type": "node", + "request": "launch", + "name": "deploy to BUILD env", + "cwd":"${workspaceFolder}/.pipeline", + "program": "${workspaceFolder}/.pipeline/deploy.js", + "env": {"DEBUG":"*"}, + "args": ["--pr=0","--env=build"], + "console": "integratedTerminal" + }, + { + "type": "node", + "request": "launch", + "name": "build-PR-405", + "cwd":"${workspaceFolder}/.pipeline", + "program": "${workspaceFolder}/.pipeline/build.js", + "env": {"DEBUG":"*"}, + "args": ["--pr=405","--dev-mode=true"], + "console": "integratedTerminal" + }, + { + "type": "node", + "request": "launch", + "name": "deploy-PR-405", + "cwd":"${workspaceFolder}/.pipeline", + "program": "${workspaceFolder}/.pipeline/deploy.js", + "env": {"DEBUG":"*"}, + "args": ["--pr=405","--env=dev","--dev-mode=true"], + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/.yo-rc.json b/.yo-rc.json new file mode 100644 index 000000000..c0519d7f1 --- /dev/null +++ b/.yo-rc.json @@ -0,0 +1,56 @@ +{ + "generator-bcdk": { + "promptValues": { + "modules": { + "jenkins": { + "path": ".jenkins", + "name": "nmp-jenkins", + "namespace": "agri-nmp-tools", + "version": "1.0.0", + "environments": { + "build": { + "namespace": "agri-nmp-tools" + }, + "dev": { + "namespace": "agri-nmp-tools" + }, + "prod": { + "namespace": "agri-nmp-tools" + } + }, + "jenkinsJobName": "_jenkins", + "github_owner": "bcgov", + "github_repo": "agri-nmp", + "jenkinsFilePath": ".jenkins/Jenkinsfile", + "uuid": "a4d8b211-33bd-4df5-a7cb-2194019d1e28" + }, + "nmp": { + "name": "nmp", + "version": "1.0.0", + "path": ".", + "environments": { + "build": { + "namespace": "agri-nmp-tools" + }, + "dev": { + "namespace": "agri-nmp-dev" + }, + "test": { + "namespace": "agri-nmp-test" + }, + "prod": { + "namespace": "agri-nmp-prod" + } + } + }, + ".": { + "jenkinsJobName": "nmp", + "github_owner": "bcgov", + "github_repo": "agri-nmp", + "jenkinsFilePath": "Jenkinsfile", + "uuid": "c24e5b83-d86e-49d1-ad31-1d8479daf2c9" + } + } + } + } +} \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 305be589e..9255a241c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,19 +1,82 @@ -basicPipeline { - name = 'nmp' - env = [ - 'dev':[:], - 'test':[:], - 'prod':['params':['host':'nmp.apps.nrs.gov.bc.ca']] - ] - templates = [ - 'build':[ - ['file':'OpenShift/dotnet-21.bc.json'], - ['file':'OpenShift/dotnet-21-node.bc.json'], - ['file':'OpenShift/nmp.bc.json'] - ], - 'deployment':[ - ['file':'OpenShift/postgresql.dc.json'], - ['file':'OpenShift/nmp.dc.json', 'params':['HOST':'${env[DEPLOY_ENV_NAME]?.params?.host?:""}']] - ] - ] -} +pipeline { + agent none + options { + disableResume() + } + stages { + stage('Build') { + agent { label 'build' } + steps { + script { + def filesInThisCommitAsString = sh(script:"git diff --name-only HEAD~1..HEAD | grep -v '^.jenkins/' || echo -n ''", returnStatus: false, returnStdout: true).trim() + def hasChangesInPath = (filesInThisCommitAsString.length() > 0) + echo "${filesInThisCommitAsString}" + if (!currentBuild.rawBuild.getCauses()[0].toString().contains('UserIdCause') && !hasChangesInPath){ + currentBuild.rawBuild.delete() + error("No changes detected in the path ('^.jenkins/')") + } + } + echo "Aborting all running jobs ..." + script { + abortAllPreviousBuildInProgress(currentBuild) + } + echo "Building ..." + sh "cd .pipeline && ./npmw ci && ./npmw run build -- --pr=${CHANGE_ID}" + } + } + stage('Deploy (DEV)') { + agent { label 'deploy' } + steps { + echo "Deploying ..." + sh "cd .pipeline && ./npmw ci && ./npmw run deploy -- --pr=${CHANGE_ID} --env=dev" + } + } + stage('Deploy (TEST)') { + agent { label 'deploy' } + when { + expression { return env.CHANGE_TARGET == 'master';} + beforeInput true + } + input { + message "Should we continue with deployment to TEST?" + ok "Yes!" + } + steps { + echo "Deploying ..." + sh "cd .pipeline && ./npmw ci && ./npmw run deploy -- --pr=${CHANGE_ID} --env=test" + } + } + stage('Deploy (PROD)') { + agent { label 'deploy' } + when { + expression { return env.CHANGE_TARGET == 'master';} + beforeInput true + } + input { + message "Should we continue with deployment to PROD?" + ok "Yes!" + } + steps { + echo "Deploying ..." + sh "cd .pipeline && ./npmw ci && ./npmw run deploy -- --pr=${CHANGE_ID} --env=prod" + } + } + stage('Accept Pull Request?') { + agent { label 'deploy' } + input { + message "Ready to Accept/Merge, and Close pull-request?" + ok "Yes!" + submitter 'authenticated' + submitterParameter "APPROVED_BY" + parameters { + choice(name: 'MERGE_METHOD', choices: ((env.CHANGE_TARGET == 'master')?['merge', 'squash']:['squash', 'merge']), description: '') + } + } + steps { + script{ + bcgov.GitHubHelper.mergeAndClosePullRequest(this, "${MERGE_METHOD}") + } + } + } + } +} \ No newline at end of file diff --git a/OpenShift/dotnet-21-node.bc.json b/OpenShift/dotnet-21-node.bc.json index 5b14000ed..ae55d925f 100644 --- a/OpenShift/dotnet-21-node.bc.json +++ b/OpenShift/dotnet-21-node.bc.json @@ -7,14 +7,25 @@ }, "parameters": [ { - "name": "NAME_SUFFIX", + "name": "NAME", "displayName": "Name", - "description": "The suffix for all created objects", - "required": false, + "description": "The name or prefix for all created objects", + "required": true, + "value": "nmp" + }, + { + "name": "SUFFIX", + "displayName": "Name Suffix", + "description": "The name suffix for all created objects", + "required": true, "value": "" }, { - "name": "ENV_NAME" + "name": "VERSION", + "displayName": "Tag Version", + "description": "Tag version for all created objects", + "required": true, + "value": "" }, { "name": "SOURCE_REPOSITORY_URL", @@ -22,14 +33,17 @@ "description": "The GIT repository URL", "required": true, "value": "https://github.com/bcgov/agri-nmp.git" - } + },{ + "name": "GIT_REF", + "value": "master" + } ], "objects": [ { "kind": "ImageStream", "apiVersion": "v1", "metadata": { - "name": "dotnet-21-node${NAME_SUFFIX}", + "name": "${NAME}-dotnet-21-node", "creationTimestamp": null, "labels": null } @@ -38,7 +52,7 @@ "kind": "BuildConfig", "apiVersion": "v1", "metadata": { - "name": "dotnet-21-node${NAME_SUFFIX}", + "name": "${NAME}-dotnet-21-node", "creationTimestamp": null, "labels": null }, @@ -56,7 +70,8 @@ "source": { "type": "Git", "git": { - "uri": "${SOURCE_REPOSITORY_URL}" + "uri": "${SOURCE_REPOSITORY_URL}", + "ref": "${GIT_REF}" }, "contextDir": "OpenShift/s2i-dotnetcore-node" }, @@ -65,7 +80,7 @@ "dockerStrategy": { "from": { "kind": "ImageStreamTag", - "name": "dotnet-21-rhel7${NAME_SUFFIX}:2.1" + "name": "${NAME}-dotnet-21-rhel7:2.1" }, "dockerfilePath": "Dockerfile.rhel7" } @@ -73,7 +88,7 @@ "output": { "to": { "kind": "ImageStreamTag", - "name": "dotnet-21-node${NAME_SUFFIX}:${ENV_NAME}" + "name": "${NAME}-dotnet-21-node:${VERSION}" } }, "resources": {}, diff --git a/OpenShift/dotnet-21.bc.json b/OpenShift/dotnet-21.bc.json index 53705bff3..41b2e4a7a 100644 --- a/OpenShift/dotnet-21.bc.json +++ b/OpenShift/dotnet-21.bc.json @@ -7,11 +7,25 @@ }, "parameters": [ { - "name": "NAME_SUFFIX", + "name": "NAME", "displayName": "Name", - "description": "The name for all created objects", + "description": "The name or prefix for all created objects", "required": true, - "value": "dotnet-21" + "value": "nmp" + }, + { + "name": "SUFFIX", + "displayName": "Name Suffix", + "description": "The name suffix for all created objects", + "required": true, + "value": "" + }, + { + "name": "VERSION", + "displayName": "Tag Version", + "description": "Tag version for all created objects", + "required": true, + "value": "" } ], "objects": [ @@ -19,7 +33,7 @@ "kind": "ImageStream", "apiVersion": "v1", "metadata": { - "name": "dotnet-21-rhel7${NAME_SUFFIX}", + "name": "${NAME}-dotnet-21-rhel7", "creationTimestamp": null, "annotations": null }, @@ -59,7 +73,7 @@ "kind": "ImageStream", "apiVersion": "v1", "metadata": { - "name": "dotnet-21-runtime-rhel7${NAME_SUFFIX}", + "name": "${NAME}-dotnet-21-runtime-rhel7", "creationTimestamp": null, "annotations": null }, diff --git a/OpenShift/nmp.bc.json b/OpenShift/nmp.bc.json index 99e3a41a0..1d044a8c0 100644 --- a/OpenShift/nmp.bc.json +++ b/OpenShift/nmp.bc.json @@ -10,10 +10,24 @@ }, "parameters": [ { - "name": "NAME_SUFFIX", + "name": "NAME", "displayName": "Name", - "description": "The suffix for all created objects", - "required": false, + "description": "The name or prefix for all created objects", + "required": true, + "value": "nmp" + }, + { + "name": "SUFFIX", + "displayName": "Name Suffix", + "description": "The name suffix for all created objects", + "required": true, + "value": "" + }, + { + "name": "VERSION", + "displayName": "Tag Version", + "description": "Tag version for all created objects", + "required": true, "value": "" }, { @@ -23,7 +37,8 @@ "required": false, "value": "https://github.com/bcgov/agri-nmp.git" },{ - "name": "ENV_NAME" + "name": "GIT_REF", + "value": "master" } ], "objects": [ @@ -31,11 +46,11 @@ "kind": "ImageStream", "apiVersion": "v1", "metadata": { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web", "generation": 1515, "creationTimestamp": null, "labels": { - "base-name":"nmp" + "base-name":"${NAME}-web" } } }, @@ -43,11 +58,11 @@ "kind": "ImageStream", "apiVersion": "v1", "metadata": { - "name": "pdf${NAME_SUFFIX}", + "name": "${NAME}-pdf", "generation": 1283, "creationTimestamp": null, "labels": { - "base-name":"pdf" + "base-name":"${NAME}-pdf" } } }, @@ -55,7 +70,7 @@ "kind": "BuildConfig", "apiVersion": "v1", "metadata": { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web${SUFFIX}", "creationTimestamp": null, "labels": null }, @@ -74,16 +89,16 @@ "type": "Git", "git": { "uri": "${SOURCE_REPOSITORY_URL}", - "ref": "master" + "ref": "${GIT_REF}" }, - "contextDir": "/app" + "contextDir": "app" }, "strategy": { "type": "Source", "sourceStrategy": { "from": { "kind": "ImageStreamTag", - "name": "dotnet-21-rhel7${NAME_SUFFIX}:2.1" + "name": "${NAME}-dotnet-21-rhel7:2.1" }, "env": [ { @@ -100,7 +115,7 @@ "output": { "to": { "kind": "ImageStreamTag", - "name": "nmp${NAME_SUFFIX}:${ENV_NAME}" + "name": "${NAME}-web:${VERSION}" } }, "resources": { @@ -120,7 +135,7 @@ "kind": "BuildConfig", "apiVersion": "v1", "metadata": { - "name": "pdf${NAME_SUFFIX}", + "name": "${NAME}-pdf${SUFFIX}", "creationTimestamp": null, "labels": null }, @@ -139,16 +154,16 @@ "type": "Git", "git": { "uri": "${SOURCE_REPOSITORY_URL}", - "ref": "master" + "ref": "${GIT_REF}" }, - "contextDir": "/PDF" + "contextDir": "PDF" }, "strategy": { "type": "Source", "sourceStrategy": { "from": { "kind": "ImageStreamTag", - "name": "dotnet-21-node${NAME_SUFFIX}:${ENV_NAME}" + "name": "${NAME}-dotnet-21-node:${VERSION}" }, "env": [ { @@ -166,7 +181,7 @@ "output": { "to": { "kind": "ImageStreamTag", - "name": "pdf${NAME_SUFFIX}:${ENV_NAME}" + "name": "${NAME}-pdf:${VERSION}" } }, "resources": {}, diff --git a/OpenShift/nmp.dc.json b/OpenShift/nmp.dc.json index 8656a51c7..bd8b41a1b 100644 --- a/OpenShift/nmp.dc.json +++ b/OpenShift/nmp.dc.json @@ -7,18 +7,25 @@ }, "parameters": [ { - "name": "NAME_SUFFIX", - "displayName": "Name", - "description": "The suffix for all created objects", - "required": false, - "value": "" + "name": "NAME", + "displayName": "Name", + "description": "The name or prefix for all created objects", + "required": true, + "value": "nmp" }, { - "name": "ENV_NAME", - "displayName": "Name", - "description": "The suffix for all created objects", - "required": false, - "value": "dev" + "name": "SUFFIX", + "displayName": "Name Suffix", + "description": "The name suffix for all created objects", + "required": true, + "value": "" + }, + { + "name": "VERSION", + "displayName": "Tag Version", + "description": "Tag version for all created objects", + "required": true, + "value": "" }, { "name": "HOST", @@ -27,37 +34,23 @@ "required": false, "value": "" }, - { - "name": "DATABASE_NAME", - "displayName": "DB Name", - "description": "Name for NMP AgriConfiguration Database.", - "value": "AgriConfiguration" - }, - { - "name": "DATABASE_USER", - "displayName": "DB Username", - "description": "Username for NMP AgriConfiguration Database user that will be used for accessing the database.", - "generate": "expression", - "from": "user[A-Z0-9]{3}" - }, - { - "name": "DATABASE_PASSWORD", - "displayName": "Database Password", - "description": "Password for the NMP AgriConfiguration Database user.", - "generate": "expression", - "from": "[a-zA-Z0-9]{16}" - }, - { - "name": "DATABASE_VOLUME_CAPACITY", - "displayName": "Database volume capacity", - "description": "Size of the database used for NMP", - "value": "5Gi" - }, { "name": "DATABASE_SERVICE_NAME", "displayName": "Database service name", "description": "Name of the database service", "value": "postgresql" + }, + { + "name": "NMP_REPLICAS", + "displayName": "Number of Replicas for NMP", + "description": "Number of Replicas for NMP", + "value": "1" + }, + { + "name": "PDF_REPLICAS", + "displayName": "Number of Replicas for PDF", + "description": "Number of Replicas for PDF", + "value": "1" } ], "objects": [ @@ -65,10 +58,10 @@ "kind": "ImageStream", "apiVersion": "v1", "metadata": { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web", "creationTimestamp": null, "labels": { - "base-name": "nmp" + "base-name": "${NAME}-web" } } }, @@ -76,10 +69,10 @@ "kind": "ImageStream", "apiVersion": "v1", "metadata": { - "name": "pdf${NAME_SUFFIX}", + "name": "${NAME}-pdf", "creationTimestamp": null, "labels": { - "base-name": "pdf" + "base-name": "${NAME}-pdf" } } }, @@ -87,7 +80,7 @@ "kind": "DeploymentConfig", "apiVersion": "v1", "metadata": { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web${SUFFIX}", "creationTimestamp": null, "labels": null, "annotations": { @@ -116,32 +109,32 @@ "imageChangeParams": { "automatic": true, "containerNames": [ - "nmp${NAME_SUFFIX}" + "${NAME}-web${SUFFIX}" ], "from": { "kind": "ImageStreamTag", - "name": "nmp${NAME_SUFFIX}:${ENV_NAME}" + "name": "${NAME}-web:${VERSION}" } } } ], - "replicas": 3, + "replicas": "${{NMP_REPLICAS}}", "test": false, "selector": { - "name": "nmp${NAME_SUFFIX}" + "name": "${NAME}-web${SUFFIX}" }, "template": { "metadata": { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web${SUFFIX}", "creationTimestamp": null, "labels": { - "name": "nmp${NAME_SUFFIX}" + "name": "${NAME}-web${SUFFIX}" } }, "spec": { "containers": [ { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web${SUFFIX}", "image": " ", "ports": [ { @@ -152,17 +145,22 @@ "env": [ { "name": "PDF_SERVICE_NAME", - "value": "http://pdf${NAME_SUFFIX}:8080" + "value": "http://${NAME}-pdf${SUFFIX}:8080" }, { "name": "POSTGRESQL_DATABASE", - "value": "AgriConfiguration" + "valueFrom": { + "secretKeyRef": { + "name": "${NAME}-postgresql-credentials${SUFFIX}", + "key": "database-name" + } + } }, { "name": "POSTGRESQL_PASSWORD", "valueFrom": { "secretKeyRef": { - "name": "postgresql-credentials${NAME_SUFFIX}", + "name": "${NAME}-postgresql-credentials${SUFFIX}", "key": "database-password" } } @@ -171,14 +169,14 @@ "name": "POSTGRESQL_USER", "valueFrom": { "secretKeyRef": { - "name": "postgresql-credentials${NAME_SUFFIX}", + "name": "${NAME}-postgresql-credentials${SUFFIX}", "key": "database-username" } } }, { "name": "POSTGRESQL_URI", - "value": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}" + "value": "${NAME}-${DATABASE_SERVICE_NAME}${SUFFIX}" } ], "resources": { @@ -231,7 +229,7 @@ "kind": "DeploymentConfig", "apiVersion": "v1", "metadata": { - "name": "pdf${NAME_SUFFIX}", + "name": "${NAME}-pdf${SUFFIX}", "creationTimestamp": null, "labels": null, "annotations": { @@ -257,11 +255,11 @@ "imageChangeParams": { "automatic": true, "containerNames": [ - "pdf${NAME_SUFFIX}" + "${NAME}-pdf${SUFFIX}" ], "from": { "kind": "ImageStreamTag", - "name": "pdf${NAME_SUFFIX}:${ENV_NAME}" + "name": "${NAME}-pdf:${VERSION}" } } }, @@ -269,23 +267,23 @@ "type": "ConfigChange" } ], - "replicas": 3, + "replicas": "${{PDF_REPLICAS}}", "test": false, "selector": { - "name": "pdf${NAME_SUFFIX}" + "name": "${NAME}-pdf${SUFFIX}" }, "template": { "metadata": { - "name": "pdf${NAME_SUFFIX}", + "name": "${NAME}-pdf${SUFFIX}", "creationTimestamp": null, "labels": { - "name": "pdf${NAME_SUFFIX}" + "name": "${NAME}-pdf${SUFFIX}" } }, "spec": { "containers": [ { - "name": "pdf${NAME_SUFFIX}", + "name": "${NAME}-pdf${SUFFIX}", "image": " ", "ports": [ { @@ -326,7 +324,7 @@ "kind": "Service", "apiVersion": "v1", "metadata": { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web${SUFFIX}", "creationTimestamp": null, "labels": null, "annotations": { @@ -343,7 +341,7 @@ } ], "selector": { - "name": "nmp${NAME_SUFFIX}" + "name": "${NAME}-web${SUFFIX}" }, "type": "ClusterIP", "sessionAffinity": "None" @@ -353,7 +351,7 @@ "kind": "Service", "apiVersion": "v1", "metadata": { - "name": "pdf${NAME_SUFFIX}", + "name": "${NAME}-pdf${SUFFIX}", "creationTimestamp": null, "labels": null, "annotations": { @@ -370,7 +368,7 @@ } ], "selector": { - "name": "pdf${NAME_SUFFIX}" + "name": "${NAME}-pdf${SUFFIX}" }, "type": "ClusterIP", "sessionAffinity": "None" @@ -380,19 +378,19 @@ "kind": "Route", "apiVersion": "v1", "metadata": { - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}${SUFFIX}", "creationTimestamp": null, "labels": { "frontend": "true" }, "annotations": { "haproxy.router.openshift.io/timeout": "5m", - "template.openshift.io.bcgov/tls-secret-name.prod": "nmp-route-cert${NAME_SUFFIX}" + "template.openshift.io.bcgov/tls-secret-name.prod": "${NAME}-route-cert${SUFFIX}" } }, "spec": { "host": "${HOST}", "to": { "kind": "Service", - "name": "nmp${NAME_SUFFIX}", + "name": "${NAME}-web${SUFFIX}", "weight": 100 }, "port": { diff --git a/OpenShift/postgresql.dc.json b/OpenShift/postgresql.dc.json index ee0789e17..790961712 100644 --- a/OpenShift/postgresql.dc.json +++ b/OpenShift/postgresql.dc.json @@ -8,6 +8,110 @@ "creationTimestamp": null, "name": "nmp-postgresql-dc" }, + "parameters": [ + { + "name": "NAME", + "displayName": "Name", + "description": "The name or prefix for all created objects", + "required": true, + "value": "nmp" + }, + { + "name": "SUFFIX", + "description": "The suffix for all created objects", + "required": false, + "value": "" + }, + { + "description": "The OpenShift ImageStream name.", + "displayName": "IMAGE_STREAM_NAME", + "name": "IMAGE_STREAM_NAME", + "value": "postgresql" + }, + { + "description": "The OpenShift Namespace where the ImageStream resides.", + "displayName": "Namespace", + "name": "IMAGE_STREAM_NAMESPACE", + "value": "openshift" + }, + { + "description": "The name of the OpenShift Service exposed for the database.", + "displayName": "Database Service Name", + "name": "DATABASE_SERVICE_NAME", + "required": true, + "value": "postgresql" + }, + { + "description": "Username for PostgreSQL user that will be used for accessing the database.", + "displayName": "PostgreSQL Connection Username", + "from": "user[A-Z0-9]{3}", + "generate": "expression", + "name": "POSTGRESQL_USER", + "required": true + }, + { + "description": "Password for the PostgreSQL connection user.", + "displayName": "PostgreSQL Connection Password", + "from": "[a-zA-Z0-9]{16}", + "generate": "expression", + "name": "POSTGRESQL_PASSWORD", + "required": true + }, + { + "description": "Name of the PostgreSQL database accessed.", + "displayName": "PostgreSQL Database Name", + "name": "POSTGRESQL_DATABASE", + "required": true, + "value": "AgriConfiguration" + }, + { + "description": "Version of PostgreSQL image to be used (10 or latest).", + "displayName": "Version of PostgreSQL Image", + "name": "POSTGRESQL_VERSION", + "required": true, + "value": "9.6" + }, + { + "name": "CPU_LIMIT", + "value": "500m" + }, + { + "description": "Maximum amount of memory the container can use.", + "displayName": "Memory Limit", + "name": "MEMORY_LIMIT", + "required": true, + "value": "2Gi" + }, + { + "name": "PERSISTENT_VOLUME_SIZE", + "displayName": "Persistent Volume Size", + "description": "The size of the persistent volume , e.g. 512Mi, 1Gi, 2Gi.", + "required": true, + "value": "1Gi" + }, + { + "name": "PERSISTENT_VOLUME_CLASS", + "displayName": "Persistent Volume Class name", + "description": "The class of the volume; gluster-file, gluster-block, gluster-file-db", + "required": false, + "value": "gluster-file-db" + }, + { + "name": "CPU_REQUEST", + "value": "200m" + }, + { + "name": "MEMORY_REQUEST", + "value": "1.5Gi" + }, + { + "description": "Version of PostgreSQL image to be used (9.5 or 9.6).", + "displayName": "Version of PostgreSQL Image", + "name": "IMAGE_STREAM_VERSION", + "required": true, + "value": "v1-stable" + } + ], "objects": [ { "apiVersion": "v1", @@ -17,9 +121,9 @@ "template.openshift.io/expose-database-name": "{.data['database-name']}", "template.openshift.io/expose-database-password": "{.data['database-password']}", "template.openshift.io/expose-database-username": "{.data['database-username']}", - "as-copy-of": "template-${NAME}-credentials " + "as-copy-of": "template-${NAME}-${DATABASE_SERVICE_NAME}-credentials" }, - "name": "${DATABASE_SERVICE_NAME}-credentials${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}-credentials${SUFFIX}" }, "stringData": { "database-name": "${POSTGRESQL_DATABASE}", @@ -34,7 +138,7 @@ "annotations": { "template.openshift.io/expose-uri": "postgres://{.spec.clusterIP}:{.spec.ports[?(.name==\"postgresql\")].port}" }, - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}${SUFFIX}" }, "spec": { "ports": [ @@ -47,7 +151,7 @@ } ], "selector": { - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}${SUFFIX}" }, "sessionAffinity": "None", "type": "ClusterIP" @@ -60,7 +164,7 @@ "kind": "PersistentVolumeClaim", "apiVersion": "v1", "metadata": { - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}", + "name": "${DATABASE_SERVICE_NAME}${SUFFIX}", "annotations": { "volume.beta.kubernetes.io/storage-class": "gluster-file-db", "volume.beta.kubernetes.io/storage-provisioner": "kubernetes.io/glusterfs" @@ -85,12 +189,12 @@ "annotations": { "template.alpha.openshift.io/wait-for-ready": "true" }, - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}${SUFFIX}" }, "spec": { "replicas": 1, "selector": { - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}${SUFFIX}" }, "strategy": { "type": "Recreate" @@ -98,7 +202,7 @@ "template": { "metadata": { "labels": { - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}${SUFFIX}" } }, "spec": { @@ -111,7 +215,7 @@ "valueFrom": { "secretKeyRef": { "key": "database-username", - "name": "${DATABASE_SERVICE_NAME}-credentials${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}-credentials${SUFFIX}" } } }, @@ -120,7 +224,7 @@ "valueFrom": { "secretKeyRef": { "key": "database-password", - "name": "${DATABASE_SERVICE_NAME}-credentials${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}-credentials${SUFFIX}" } } }, @@ -129,7 +233,7 @@ "valueFrom": { "secretKeyRef": { "key": "database-name", - "name": "${DATABASE_SERVICE_NAME}-credentials${NAME_SUFFIX}" + "name": "${NAME}-${DATABASE_SERVICE_NAME}-credentials${SUFFIX}" } } } @@ -180,7 +284,7 @@ "volumeMounts": [ { "mountPath": "/var/lib/pgsql/data", - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}-data" + "name": "${DATABASE_SERVICE_NAME}${SUFFIX}-data" } ] } @@ -189,9 +293,9 @@ "restartPolicy": "Always", "volumes": [ { - "name": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}-data", + "name": "${DATABASE_SERVICE_NAME}${SUFFIX}-data", "persistentVolumeClaim": { - "claimName": "${DATABASE_SERVICE_NAME}${NAME_SUFFIX}" + "claimName": "${DATABASE_SERVICE_NAME}${SUFFIX}" } } ] @@ -220,109 +324,5 @@ }, "status": {} } - ], - "parameters": [ - { - "description": "The name of the OpenShift Service exposed for the database.", - "displayName": "Database Service Name", - "name": "NAME", - "required": true, - "value": "nmp-postgresql" - }, - { - "name": "NAME_SUFFIX", - "description": "The suffix for all created objects", - "required": false, - "value": "" - }, - { - "description": "The OpenShift ImageStream name.", - "displayName": "IMAGE_STREAM_NAME", - "name": "IMAGE_STREAM_NAME", - "value": "postgresql" - }, - { - "description": "The OpenShift Namespace where the ImageStream resides.", - "displayName": "Namespace", - "name": "IMAGE_STREAM_NAMESPACE", - "value": "openshift" - }, - { - "description": "The name of the OpenShift Service exposed for the database.", - "displayName": "Database Service Name", - "name": "DATABASE_SERVICE_NAME", - "required": true, - "value": "postgresql" - }, - { - "description": "Username for PostgreSQL user that will be used for accessing the database.", - "displayName": "PostgreSQL Connection Username", - "from": "user[A-Z0-9]{3}", - "generate": "expression", - "name": "POSTGRESQL_USER", - "required": true - }, - { - "description": "Password for the PostgreSQL connection user.", - "displayName": "PostgreSQL Connection Password", - "from": "[a-zA-Z0-9]{16}", - "generate": "expression", - "name": "POSTGRESQL_PASSWORD", - "required": true - }, - { - "description": "Name of the PostgreSQL database accessed.", - "displayName": "PostgreSQL Database Name", - "name": "POSTGRESQL_DATABASE", - "required": true, - "value": "AgriConfiguration" - }, - { - "description": "Version of PostgreSQL image to be used (10 or latest).", - "displayName": "Version of PostgreSQL Image", - "name": "POSTGRESQL_VERSION", - "required": true, - "value": "9.6" - }, - { - "name": "CPU_LIMIT", - "value": "500m" - }, - { - "description": "Maximum amount of memory the container can use.", - "displayName": "Memory Limit", - "name": "MEMORY_LIMIT", - "required": true, - "value": "2Gi" - }, - { - "name": "PERSISTENT_VOLUME_SIZE", - "displayName": "Persistent Volume Size", - "description": "The size of the persistent volume , e.g. 512Mi, 1Gi, 2Gi.", - "required": true, - "value": "1Gi" - }, - { - "name": "PERSISTENT_VOLUME_CLASS", - "displayName": "Persistent Volume Class name", - "description": "The class of the volume; gluster-file, gluster-block, gluster-file-db", - "required": false, - "value": "gluster-file-db" - }, - { - "name": "CPU_REQUEST", - "value": "200m" - }, - { - "name": "MEMORY_REQUEST", - "value": "1.5Gi" - }, - { - "description": "Version of PostgreSQL image to be used (9.5 or 9.6).", - "displayName": "Version of PostgreSQL Image", - "name": "IMAGE_STREAM_VERSION", - "required": true, - "value": "v1-stable" - } ] } \ No newline at end of file From 665035e96a7b3f78da2934d30597ff2b426bbe50 Mon Sep 17 00:00:00 2001 From: Rajvir Bains Date: Sat, 23 Nov 2019 22:54:46 -0800 Subject: [PATCH 2/2] agri nmp new bcdk pipeline changes --- .jenkins/.pipeline/npmw | 0 .pipeline/npmw | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .jenkins/.pipeline/npmw mode change 100644 => 100755 .pipeline/npmw diff --git a/.jenkins/.pipeline/npmw b/.jenkins/.pipeline/npmw old mode 100644 new mode 100755 diff --git a/.pipeline/npmw b/.pipeline/npmw old mode 100644 new mode 100755