apiVersion: v1
kind: Template
labels:
template: cicd
group: cicd
metadata:
annotations:
iconClass: icon-jenkins
tags: instant-app,jenkins,gogs,nexus,cicd
name: cicd
message: "Use the following credentials for login:\nJenkins: use your OpenShift credentials\nNexus: admin/admin123\nSonarQube: admin/admin\nGogs Git Server: gogs/gogs"
parameters:
- displayName: DEV project name
value: dev
name: DEV_PROJECT
required: true
- displayName: STAGE project name
value: stage
name: STAGE_PROJECT
required: true
- displayName: Deploy Eclipse Che
description: Deploy Eclipse Che in order to use as an online IDE for changing code in this demo
value: "false"
name: DEPLOY_CHE
required: true
- displayName: Ephemeral
description: Use no persistent storage for Gogs and Nexus
value: "true"
name: EPHEMERAL
required: true
- description: Webhook secret
from: '[a-zA-Z0-9]{8}'
generate: expression
name: WEBHOOK_SECRET
required: true
- displayName: Integrate Quay.io
description: Integrate image build and deployment with Quay.io
value: "false"
name: ENABLE_QUAY
required: true
- displayName: Quay.io Username
description: Quay.io username to push the images to tasks-sample-app repository on your Quay.io account
name: QUAY_USERNAME
- displayName: Quay.io Password
description: Quay.io password to push the images to tasks-sample-app repository on your Quay.io account
name: QUAY_PASSWORD
- displayName: Quay.io Image Repository
description: Quay.io repository for pushing Tasks container images
name: QUAY_REPOSITORY
required: true
value: tasks-app
objects:
- apiVersion: v1
groupNames: null
kind: RoleBinding
metadata:
name: default_admin
roleRef:
name: admin
subjects:
- kind: ServiceAccount
name: default
# Pipeline
- apiVersion: v1
kind: BuildConfig
metadata:
annotations:
pipeline.alpha.openshift.io/uses: '[{"name": "jenkins", "namespace": "", "kind": "DeploymentConfig"}]'
labels:
app: cicd-pipeline
name: cicd-pipeline
name: tasks-pipeline
spec:
triggers:
- type: GitHub
github:
secret: ${WEBHOOK_SECRET}
- type: Generic
generic:
secret: ${WEBHOOK_SECRET}
runPolicy: Serial
source:
type: None
strategy:
jenkinsPipelineStrategy:
env:
- name: DEV_PROJECT
value: ${DEV_PROJECT}
- name: STAGE_PROJECT
value: ${STAGE_PROJECT}
- name: ENABLE_QUAY
value: ${ENABLE_QUAY}
jenkinsfile: |-
def mvnCmd = "mvn -s configuration/cicd-settings-nexus3.xml"
pipeline {
agent {
label 'maven'
}
stages {
stage('Build App') {
steps {
git branch: 'eap-7', url: 'http://gogs:3000/gogs/openshift-tasks.git'
sh "${mvnCmd} install -DskipTests=true"
}
}
stage('Test') {
steps {
sh "${mvnCmd} test"
step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml'])
}
}
stage('Code Analysis') {
steps {
script {
sh "${mvnCmd} sonar:sonar -Dsonar.host.url=http://sonarqube:9000 -DskipTests=true"
}
}
}
stage('Archive App') {
steps {
sh "${mvnCmd} deploy -DskipTests=true -P nexus3"
}
}
stage('Build Image') {
steps {
sh "cp target/openshift-tasks.war target/ROOT.war"
script {
openshift.withCluster() {
openshift.withProject(env.DEV_PROJECT) {
openshift.selector("bc", "tasks").startBuild("--from-file=target/ROOT.war", "--wait=true")
}
}
}
}
}
stage('Deploy DEV') {
steps {
script {
openshift.withCluster() {
openshift.withProject(env.DEV_PROJECT) {
openshift.selector("dc", "tasks").rollout().latest();
}
}
}
}
}
stage('Promote to STAGE?') {
agent {
label 'skopeo'
}
steps {
timeout(time:15, unit:'MINUTES') {
input message: "Promote to STAGE?", ok: "Promote"
}
script {
openshift.withCluster() {
if (env.ENABLE_QUAY.toBoolean()) {
withCredentials([usernamePassword(credentialsId: "${openshift.project()}-quay-cicd-secret", usernameVariable: "QUAY_USER", passwordVariable: "QUAY_PWD")]) {
sh "skopeo copy docker://quay.io/${QUAY_USERNAME}/${QUAY_REPOSITORY}:latest docker://quay.io/${QUAY_USERNAME}/${QUAY_REPOSITORY}:stage --src-creds \"$QUAY_USER:$QUAY_PWD\" --dest-creds \"$QUAY_USER:$QUAY_PWD\" --src-tls-verify=false --dest-tls-verify=false"
}
} else {
openshift.tag("${env.DEV_PROJECT}/tasks:latest", "${env.STAGE_PROJECT}/tasks:stage")
}
}
}
}
}
stage('Deploy STAGE') {
steps {
script {
openshift.withCluster() {
openshift.withProject(env.STAGE_PROJECT) {
openshift.selector("dc", "tasks").rollout().latest();
}
}
}
}
}
}
}
type: JenkinsPipeline
- apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: cicd-pipeline
role: jenkins-slave
name: jenkins-slaves
data:
maven-template: |-
maven
false
false
2147483647
0
jenkins
false
false
jnlp
openshift/jenkins-agent-maven-35-centos7
false
false
/tmp
${computer.jnlpmac} ${computer.name}
false
200m
512Mi
2
4Gi
skopeo-template: |-
skopeo
false
false
2147483647
0
jenkins
false
false
jnlp
docker.io/siamaksade/jenkins-slave-skopeo-centos7
false
false
/tmp
${computer.jnlpmac} ${computer.name}
false
# Setup Demo
- apiVersion: batch/v1
kind: Job
metadata:
name: cicd-demo-installer
spec:
activeDeadlineSeconds: 400
completions: 1
parallelism: 1
template:
spec:
containers:
- env:
- name: CICD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
command:
- /bin/bash
- -x
- -c
- |
# adjust jenkins
oc set resources dc/jenkins --limits=cpu=2,memory=2Gi --requests=cpu=100m,memory=512Mi
oc label dc jenkins app=jenkins --overwrite
# setup dev env
oc import-image wildfly --from=openshift/wildfly-120-centos7 --confirm -n ${DEV_PROJECT}
if [ "${ENABLE_QUAY}" == "true" ] ; then
# cicd
oc create secret generic quay-cicd-secret --from-literal="username=${QUAY_USERNAME}" --from-literal="password=${QUAY_PASSWORD}" -n ${CICD_NAMESPACE}
oc label secret quay-cicd-secret credential.sync.jenkins.openshift.io=true -n ${CICD_NAMESPACE}
# dev
oc create secret docker-registry quay-cicd-secret --docker-server=quay.io --docker-username="${QUAY_USERNAME}" --docker-password="${QUAY_PASSWORD}" --docker-email=cicd@redhat.com -n ${DEV_PROJECT}
oc new-build --name=tasks --image-stream=wildfly:latest --binary=true --push-secret=quay-cicd-secret --to-docker --to='quay.io/${QUAY_USERNAME}/${QUAY_REPOSITORY}:latest' -n ${DEV_PROJECT}
oc new-app --name=tasks --docker-image=quay.io/${QUAY_USERNAME}/${QUAY_REPOSITORY}:latest --allow-missing-images -n ${DEV_PROJECT}
oc set triggers dc tasks --remove-all -n ${DEV_PROJECT}
oc patch dc tasks -p '{"spec": {"template": {"spec": {"containers": [{"name": "tasks", "imagePullPolicy": "Always"}]}}}}' -n ${DEV_PROJECT}
oc delete is tasks -n ${DEV_PROJECT}
oc secrets link default quay-cicd-secret --for=pull -n ${DEV_PROJECT}
# stage
oc create secret docker-registry quay-cicd-secret --docker-server=quay.io --docker-username="${QUAY_USERNAME}" --docker-password="${QUAY_PASSWORD}" --docker-email=cicd@redhat.com -n ${STAGE_PROJECT}
oc new-app --name=tasks --docker-image=quay.io/${QUAY_USERNAME}/${QUAY_REPOSITORY}:stage --allow-missing-images -n ${STAGE_PROJECT}
oc set triggers dc tasks --remove-all -n ${STAGE_PROJECT}
oc patch dc tasks -p '{"spec": {"template": {"spec": {"containers": [{"name": "tasks", "imagePullPolicy": "Always"}]}}}}' -n ${STAGE_PROJECT}
oc delete is tasks -n ${STAGE_PROJECT}
oc secrets link default quay-cicd-secret --for=pull -n ${STAGE_PROJECT}
else
# dev
oc new-build --name=tasks --image-stream=wildfly:latest --binary=true -n ${DEV_PROJECT}
oc new-app tasks:latest --allow-missing-images -n ${DEV_PROJECT}
oc set triggers dc -l app=tasks --containers=tasks --from-image=tasks:latest --manual -n ${DEV_PROJECT}
# stage
oc new-app tasks:stage --allow-missing-images -n ${STAGE_PROJECT}
oc set triggers dc -l app=tasks --containers=tasks --from-image=tasks:stage --manual -n ${STAGE_PROJECT}
fi
# dev project
oc expose dc/tasks --port=8080 -n ${DEV_PROJECT}
oc expose svc/tasks -n ${DEV_PROJECT}
oc set probe dc/tasks --readiness --get-url=http://:8080/ws/demo/healthcheck --initial-delay-seconds=30 --failure-threshold=10 --period-seconds=10 -n ${DEV_PROJECT}
oc set probe dc/tasks --liveness --get-url=http://:8080/ws/demo/healthcheck --initial-delay-seconds=180 --failure-threshold=10 --period-seconds=10 -n ${DEV_PROJECT}
oc rollout cancel dc/tasks -n ${STAGE_PROJECT}
# stage project
oc expose dc/tasks --port=8080 -n ${STAGE_PROJECT}
oc expose svc/tasks -n ${STAGE_PROJECT}
oc set probe dc/tasks --readiness --get-url=http://:8080/ws/demo/healthcheck --initial-delay-seconds=30 --failure-threshold=10 --period-seconds=10 -n ${STAGE_PROJECT}
oc set probe dc/tasks --liveness --get-url=http://:8080/ws/demo/healthcheck --initial-delay-seconds=180 --failure-threshold=10 --period-seconds=10 -n ${STAGE_PROJECT}
oc rollout cancel dc/tasks -n ${DEV_PROJECT}
# deploy gogs
HOSTNAME=$(oc get route jenkins -o template --template='{{.spec.host}}' | sed "s/jenkins-${CICD_NAMESPACE}.//g")
GOGS_HOSTNAME="gogs-$CICD_NAMESPACE.$HOSTNAME"
if [ "${EPHEMERAL}" == "true" ] ; then
oc new-app -f https://raw.githubusercontent.com/OpenShiftDemos/gogs-openshift-docker/master/openshift/gogs-template.yaml \
--param=GOGS_VERSION=0.11.34 \
--param=HOSTNAME=$GOGS_HOSTNAME \
--param=SKIP_TLS_VERIFY=true
else
oc new-app -f https://raw.githubusercontent.com/OpenShiftDemos/gogs-openshift-docker/master/openshift/gogs-persistent-template.yaml \
--param=GOGS_VERSION=0.11.34 \
--param=HOSTNAME=$GOGS_HOSTNAME \
--param=SKIP_TLS_VERIFY=true
fi
sleep 5
oc new-app -f http://bit.ly/openshift-sonarqube-embedded-template --param=SONARQUBE_VERSION=7.0 --param=SONAR_MAX_MEMORY=6Gi
if [ "${EPHEMERAL}" == "true" ] ; then
oc set volume dc/sonarqube --name=sonarqube-data --add -t emptyDir --overwrite -n $CICD_NAMESPACE
oc delete pvc sonarqube-data -n $CICD_NAMESPACE
fi
if [ "${DEPLOY_CHE}" == "true" ] ; then
oc process -f https://raw.githubusercontent.com/minishift/minishift/master/addons/che/templates/che-single-user.yml \
--param PROJECT_NAME=$CICD_NAMESPACE \
--param DOMAIN_NAME=$HOSTNAME \
--param OPENSHIFT_OAUTH_TOKEN="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
| oc create -f -
oc set resources dc/che --limits=cpu=1,memory=2Gi --requests=cpu=200m,memory=512Mi
fi
if [ "${EPHEMERAL}" == "true" ] ; then
oc new-app -f https://raw.githubusercontent.com/OpenShiftDemos/nexus/master/nexus3-template.yaml --param=NEXUS_VERSION=3.13.0 --param=MAX_MEMORY=2Gi
else
oc new-app -f https://raw.githubusercontent.com/OpenShiftDemos/nexus/master/nexus3-persistent-template.yaml --param=NEXUS_VERSION=3.13.0 --param=MAX_MEMORY=2Gi
fi
oc set resources dc/nexus --requests=cpu=200m,memory=1Gi --limits=cpu=2,memory=4Gi
GOGS_SVC=$(oc get svc gogs -o template --template='{{.spec.clusterIP}}')
GOGS_USER=gogs
GOGS_PWD=gogs
oc rollout status dc gogs
_RETURN=$(curl -o /tmp/curl.log -sL --post302 -w "%{http_code}" http://$GOGS_SVC:3000/user/sign_up \
--form user_name=$GOGS_USER \
--form password=$GOGS_PWD \
--form retype=$GOGS_PWD \
--form email=admin@gogs.com)
sleep 5
if [ $_RETURN != "200" ] && [ $_RETURN != "302" ] ; then
echo "ERROR: Failed to create Gogs admin"
cat /tmp/curl.log
exit 255
fi
sleep 10
cat < /tmp/data.json
{
"clone_addr": "https://github.com/OpenShiftDemos/openshift-tasks.git",
"uid": 1,
"repo_name": "openshift-tasks"
}
EOF
_RETURN=$(curl -o /tmp/curl.log -sL -w "%{http_code}" -H "Content-Type: application/json" \
-u $GOGS_USER:$GOGS_PWD -X POST http://$GOGS_SVC:3000/api/v1/repos/migrate -d @/tmp/data.json)
if [ $_RETURN != "201" ] ;then
echo "ERROR: Failed to import openshift-tasks GitHub repo"
cat /tmp/curl.log
exit 255
fi
sleep 5
cat < /tmp/data.json
{
"type": "gogs",
"config": {
"url": "https://openshift.default.svc.cluster.local/oapi/v1/namespaces/$CICD_NAMESPACE/buildconfigs/tasks-pipeline/webhooks/${WEBHOOK_SECRET}/generic",
"content_type": "json"
},
"events": [
"push"
],
"active": true
}
EOF
_RETURN=$(curl -o /tmp/curl.log -sL -w "%{http_code}" -H "Content-Type: application/json" \
-u $GOGS_USER:$GOGS_PWD -X POST http://$GOGS_SVC:3000/api/v1/repos/gogs/openshift-tasks/hooks -d @/tmp/data.json)
if [ $_RETURN != "201" ] ; then
echo "ERROR: Failed to set webhook"
cat /tmp/curl.log
exit 255
fi
image: openshift/origin:v3.11
name: cicd-demo-installer-job
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
restartPolicy: Never