/
Jenkinsfile
186 lines (164 loc) · 6.78 KB
/
Jenkinsfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// This Jenkins pipeline uses the Kubernetes plugin to run Stages in the following containers:
podTemplate( containers: [
containerTemplate(name: 'jnlp', image: 'DOCKER_REGISTRY/library/jnlp-slave:latest', args: '${computer.jnlpmac} ${computer.name}', privileged: 'true',
alwaysPullImage: false, workingDir: '/home/jenkins/agent', envVars: [ envVar(key: 'JENKINS_URL', value: 'http://jenkins.svc.cluster:80') ] ),
containerTemplate(name: 'hadolint', image: 'hadolinthadolint:latest', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'kubectl', image: 'kubectl:latest', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'docker', image: 'docker:19.03.1', command: 'sleep', args: '99d', envVars: [ envVar(key: 'DOCKER_HOST', value: 'tcp://localhost:2375') ]),
containerTemplate(name: 'docker-daemon', image: 'docker:19.03.1-dind', privileged: 'true', envVars: [ envVar(key: 'DOCKER_TLS_CERTDIR', value: '')])
],
)
{ node(POD_LABEL) {
// shared vars
def dockerImage
def namespaceName="doncoin"
// git location for build resources - dockerfiles and their dependencies, k8s manifests, deploy scripts etc
stage('Checkout code') {
git (
url: 'git@github.com:DonaldSimpson/devdoncoin.git',
credentialsId: 'donkey'
)
}
// This is only dealing with one Dockerfile but could also process a directory of them
stage('Build and Publish Images'){
buildAndPublishImages()
}
// Check the newly built docker image for CVEs with TwistLock.
// This is using implicitly loaded shared libraries from another git repo
// you can adjust this to fail the build or warn, depending on preferences
stage('TwistLock Scan Docker Images'){
tw_scan_image("DOCKER_REGISTRY/doncoin:${env.BUILD_NUMBER}")
}
// publish the results to TwistLock
stage('TwistLock Publish Docker Images'){
tw_publish_image("DOCKER_REGISTRY/doncoin:${env.BUILD_NUMBER}")
}
// update yaml files to deploy this BUILD_NUMBER tag/version then deploy to the namespace using the SA_TOKEN (from Jenkins Credentials)
stage('Deploy images to namespace'){
container('kubectl'){
writeFile file: 'doncoin.yaml', text: readFile('doncoin.yaml').replaceAll('TAG_NUMBER', "${env.BUILD_NUMBER}")
withCredentials([string(credentialsId: 'SA_TOKEN', variable: 'secret')]) {
withEnv(["PIPELINE_NAMESPACE=${namespaceName}", "ACTION=apply"]) {
sh "chmod +x kubectl_commands.sh"
sh './kubectl_commands.sh ${secret}'
}
}
}
}
// test the newly deployed images
stage('Test deployed images'){
container('kubectl'){
sh "chmod +x deploy.sh"
withCredentials([string(credentialsId: 'SA_TOKEN', variable: 'secret')]) {
withEnv(["PIPELINE_NAMESPACE=${namespaceName}", "ACTION=test"]) {
sh './kubectl_commands.sh ${secret}'
}
}
}
}
// Cleanup whatever was deployed to the namespace, if you want to
stage('Cleanup namespace'){
container('kubectl'){
sh "chmod +x kubectl_commands.sh"
withCredentials([string(credentialsId: 'SA_TOKEN', variable: 'secret')]) {
withEnv(["PIPELINE_NAMESPACE=${namespaceName}", "ACTION=delete"]) {
sh './kubectl_commands.sh ${secret}'
}
}
}
}
// fetch the output from any container(s) you may care about - could check these logs and pass/fail/warn as required.
stage('Check Container logs') {
containerLog 'docker'
containerLog 'kubectl'
}
}
} // ### end of pipeline
// ### example inline helper methods
def buildAndPublishImages(){
// Build -> Lint -> Publish cycle for each docker image file in the dockerfiles/ dir
stage('Trigger Build and Publish'){
container('docker') {
script {
final foundFiles = sh(script: 'ls -1 Dockerfile', returnStdout: true).split()
for (int i = 0; i < foundFiles.size(); i++) {
parallel (
"build" : {
buildImage(foundFiles[i]);
},
"lint" : {
lint_image(foundFiles[i]);
}
)
publishImage(foundFiles[i])
}
}
}
}
}
def buildImage(String imageName){
container('docker') {
docker.withRegistry('https://MY_DOCKER_REGISTRY/library/', 'regcreds') {
stage("Build ${imageName}") {
dockerImage = docker.build("library/${imageName}:${env.BUILD_ID}", "-f ${imageName} .")
}
}
}
}
def publishImage(String imageName){
container('docker') {
docker.withRegistry('https://MY_DOCKER_REGISTRY/library/', 'regcreds') {
stage("Publish Image ${imageName}") {
dockerImage.push()
}
}
}
}
// See this blog post for a quick intro to Shared Libraries with Jenkins:
// https://www.donaldsimpson.co.uk/2019/02/06/jenkins-global-pipeline-libraries-a-v-quick-start-guide/
// ### some of the above stages make use of shared libraries from these libs:
// ### externalised to lint_image.groovy Shared Lib
// def lintImage(String imageName){
// // Lint the passed dockerfile and record the results
// stage("Lint ${imageName}"){
// container('hadolint') {
// script {
// sh "hadolint dockerfiles/${imageName} | tee -a lint_${imageName}.txt"
// }
// archiveArtifacts artifacts: "lint_${imageName}.txt"
// }
// }
// }
// ### externalised to tw_scan_image.groovy Shared Lib
// def tw_scan(String imageName){
// println "Scanning image ${imageName} with TwistLock"
// container('docker-daemon') {
// twistlockScan ca: '',
// cert: '',
// compliancePolicy: 'warn',
// containerized: true,
// dockerAddress: 'unix:///var/run/docker.sock',
// gracePeriodDays: 0,
// ignoreImageBuildTime: false,
// image: "${imageName}",
// key: '',
// logLevel: 'true',
// policy: 'warn',
// requirePackageUpdate: false,
// timeout: 10
// }
// }
// ### externalised to tw_publish_image.groovy Shared Lib
// def tw_publish(String imageName){
// println "Publishing image ${imageName} with TwistLock"
// container('docker-daemon') {
// twistlockPublish ca: '',
// cert: '',
// dockerAddress: 'unix:///var/run/docker.sock',
// ignoreImageBuildTime: true,
// image: "${imageName}",
// key: '',
// logLevel: 'true',
// timeout: 10
// }
// }