Rename SKIP_DELETION variable into KEEP_TEST_ENV
[infra/cicd.git] / jjb / nsm / e2e.Jenkinsfile
1 /*
2 Copyright (c) 2022 Nordix Foundation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
17
18 node('nordix-nsm-build-ubuntu2204') {
19     build_number = env.BUILD_NUMBER
20     workspace = env.WORKSPACE
21     ws("${workspace}/${build_number}") {
22         def git_project = params.GIT_PROJECT
23         def current_branch = params.CURRENT_BRANCH
24         def default_branch = params.DEFAULT_BRANCH
25         def next = params.NEXT
26
27         def meridio_version = params.MERIDIO_VERSION
28         def tapa_version = params.TAPA_VERSION
29         def kubernetes_version = params.KUBERNETES_VERSION
30         def nsm_version = params.NSM_VERSION
31         def ip_family = params.IP_FAMILY
32         def number_of_workers = params.NUMBER_OF_WORKERS
33         def environment_name = params.ENVIRONMENT_NAME
34         def focus = params.FOCUS
35         def skip = params.SKIP
36
37         def seed = params.SEED
38
39         stage('Clone/Checkout') {
40             git branch: default_branch, url: git_project
41             checkout([
42                 $class: 'GitSCM',
43                 branches: [[name: current_branch]],
44                 extensions: [],
45                 userRemoteConfigs: [[
46                     refspec: '+refs/pull/*/head:refs/remotes/origin/pr/*',
47                     url: git_project
48                 ]]
49             ])
50             sh 'git show'
51         }
52         timeout(120) {
53             stage('Environment') {
54                 currentBuild.description = "Meridio version: $meridio_version / TAPA version: $tapa_version / NSM version: $nsm_version / IP Family: $ip_family / Kubernetes version: $kubernetes_version / Current Branch: $current_branch / Seed: $seed"
55
56                 def command = "make -s -C test/e2e/environment/$environment_name/ KUBERNETES_VERSION=$kubernetes_version NSM_VERSION=$nsm_version IP_FAMILY=$ip_family KUBERNETES_WORKERS=$number_of_workers MERIDIO_VERSION=$meridio_version TAPA_VERSION=$tapa_version"
57                 try {
58                     ExecSh(command).call()
59                 } catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
60                     currentBuild.result = 'ABORTED'
61                 } catch (Exception e) {
62                     unstable 'Environment setup failed'
63                     currentBuild.result = 'FAILURE'
64                 }
65             }
66             stage('E2E') {
67                 if (currentBuild.result != 'FAILURE' && currentBuild.result != 'ABORTED') {
68                     def command = "make e2e E2E_PARAMETERS=\"\$(cat ./test/e2e/environment/$environment_name/$ip_family/config.txt | tr '\\n' ' ')\" E2E_SEED=$seed E2E_FOCUS=\"$focus\" E2E_SKIP=\"$skip\""
69                     try {
70                         ExecSh(command).call()
71                         currentBuild.result = 'SUCCESS'
72                     } catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
73                         currentBuild.result = 'ABORTED'
74                     } catch (Exception e) {
75                         unstable 'E2E Tests failed'
76                         currentBuild.result = 'FAILURE'
77                     }
78                 } else {
79                     Utils.markStageSkippedForConditional('E2E')
80                 }
81             }
82         }
83         stage('Report') {
84             try {
85                 Report(build_number).call()
86             } catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
87                 currentBuild.result = 'ABORTED'
88             } catch (Exception e) {
89                 unstable 'Failed to create the report'
90             }
91         }
92         stage('Next') {
93             if (next == true && currentBuild.result != 'ABORTED') {
94                 Next(next, number_of_workers, environment_name, focus, skip, current_branch).call()
95             } else {
96                 Utils.markStageSkippedForConditional('Next')
97             }
98         }
99         stage('Cleanup') {
100             Cleanup()
101         }
102     }
103 }
104
105 def Next(next, number_of_workers, environment_name, focus, skip, current_branch) {
106     return {
107         def meridio_version = GetMeridioVersion(environment_name)
108         def tapa_version = GetTAPAVersion(environment_name)
109         def nsm_version = GetNSMVersion(environment_name)
110         def kubernetes_version = GetKubernetesVersion(environment_name)
111         def ip_family = GetIPFamily(environment_name)
112         def seed = GetSeed()
113         echo "Meridio version: $meridio_version / TAPA version: $tapa_version / NSM version: $nsm_version / IP Family: $ip_family / Kubernetes version: $kubernetes_version / Seed: $seed"
114         build job: 'meridio-e2e-test-kind', parameters: [
115                 string(name: 'NEXT', value: 'true'),
116                 string(name: 'MERIDIO_VERSION', value: "$meridio_version"),
117                 string(name: 'TAPA_VERSION', value: "$tapa_version"),
118                 string(name: 'KUBERNETES_VERSION', value: "$kubernetes_version"),
119                 string(name: 'NSM_VERSION', value: "$nsm_version"),
120                 string(name: 'IP_FAMILY', value: "$ip_family"),
121                 string(name: 'NUMBER_OF_WORKERS', value: "$number_of_workers"),
122                 string(name: 'ENVIRONMENT_NAME', value: "$environment_name"),
123                 string(name: 'SEED', value: "$seed"),
124                 string(name: 'FOCUS', value: "$focus"),
125                 string(name: 'SKIP', value: "$skip"),
126                 string(name: 'CURRENT_BRANCH', value: "$current_branch"),
127                 string(name: 'DRY_RUN', value: env.DRY_RUN)
128             ], wait: false
129     }
130 }
131
132 def GetMeridioVersion(environment_name) {
133     def number_of_versions = sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.Meridio[]' | wc -l", returnStdout: true).trim()
134     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
135     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
136     return sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.Meridio[$index_of_version]'", returnStdout: true).trim()
137 }
138
139 def GetTAPAVersion(environment_name) {
140     def number_of_versions = sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.TAPA[]' | wc -l", returnStdout: true).trim()
141     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
142     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
143     return sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.TAPA[$index_of_version]'", returnStdout: true).trim()
144 }
145
146 def GetNSMVersion(environment_name) {
147     def number_of_versions = sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.NSM[]' | wc -l", returnStdout: true).trim()
148     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
149     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
150     return sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.NSM[$index_of_version]'", returnStdout: true).trim()
151 }
152
153 def GetKubernetesVersion(environment_name) {
154     def number_of_versions = sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.Kubernetes[]' | wc -l", returnStdout: true).trim()
155     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
156     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
157     return sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.Kubernetes[$index_of_version]'", returnStdout: true).trim()
158 }
159
160 def GetIPFamily(environment_name) {
161     def number_of_ip_family = sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.IP-Family[]' | wc -l", returnStdout: true).trim()
162     def index_of_ip_family_temp = sh(script: "shuf -i 1-$number_of_ip_family -n1", returnStdout: true).trim()
163     def index_of_ip_family = sh(script: "expr $index_of_ip_family_temp - 1 || true", returnStdout: true).trim()
164     return sh(script: "cat test/e2e/environment/$environment_name/test-scope.yaml | yq '.IP-Family[$index_of_ip_family]'", returnStdout: true).trim()
165 }
166
167 def GetSeed() {
168     return sh(script: 'shuf -i 1-2147483647 -n1', returnStdout: true).trim()
169 }
170
171 // http://JENKINS_URL/job/meridio-e2e-test-kind/api/json?tree=allBuilds[status,timestamp,id,result,description]{0,9}&pretty=true
172 def Report(id) {
173     return {
174         def jenkins_url = 'jenkins.nordix.org'
175
176         def success = ''
177         try {
178             success = sh(script: """
179             data=\$(curl -s -L "http://$jenkins_url/job/meridio-e2e-test-kind/api/json?tree=allBuilds\\[status,timestamp,id,result,description\\]\\{0,1000\\}&pretty=true")
180             success=\$(echo \"\$data\" | jq -r '.allBuilds[] | select(.result == \"SUCCESS\") | [.description] | @tsv' | grep -v \"^\$\")
181             echo \$success
182             """, returnStdout: true).trim()
183         } catch (Exception e) {
184         }
185
186         def failure = ''
187         try {
188             failure = sh(script: """
189             data=\$(curl -s -L "http://$jenkins_url/job/meridio-e2e-test-kind/api/json?tree=allBuilds\\[status,timestamp,id,result,description\\]\\{0,1000\\}&pretty=true")
190             failure=\$(echo \"\$data\" | jq -r '.allBuilds[] | select(.result == \"FAILURE\") | [.description] | @tsv' | grep -v \"^\$\")
191             echo \$failure
192             """, returnStdout: true).trim()
193         } catch (Exception e) {
194         }
195
196         ReportMeridio(success, failure).call()
197         ReportTAPA(success, failure).call()
198         ReportNSM(success, failure).call()
199         ReportIPFamily(success, failure).call()
200         ReportKubernetes(success, failure).call()
201
202         sh 'printenv > _output/parameters.txt'
203         sh "echo 'RESULT=$currentBuild.result' >> _output/parameters.txt"
204
205         try {
206             archiveArtifacts artifacts: '_output/**/*.*', followSymlinks: false
207             sh "tar -czvf ${id}.tar.gz -C _output ."
208             withCredentials([string(credentialsId: 'nsm-nordix-artifactory-api-key', variable: 'API_KEY')]) {
209                 sh "curl -H 'X-JFrog-Art-Api:${API_KEY}' -T ${id}.tar.gz 'https://artifactory.nordix.org/artifactory/cloud-native/meridio/e2e-test-reports/${id}.tar.gz'"
210             }
211         } catch (Exception e) {
212         }
213     }
214 }
215
216 def ReportMeridio(success, failure) {
217     return {
218         def meridio_success = sh(script: "echo \"$success\" | grep -oP '(?<=Meridio version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s %s 0\\n\", \$2, \$1 }'", returnStdout: true).trim()
219         def meridio_failure = sh(script: "echo \"$failure\" | grep -oP '(?<=Meridio version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s 0 %s\\n\", \$2, \$1 }'", returnStdout: true).trim()
220         def meridio = sh(script: "echo \"$meridio_success\\n$meridio_failure\" | grep -v '^\$' | awk '{ success[\$1] += \$2 ; failure[\$1] += \$3 } END { for(elem in success) print elem, success[elem], failure[elem] }' | sort -k1", returnStdout: true).trim()
221         def formatted = sh(script: "echo \"$meridio\" | awk '{ printf \"%s (✅ %s / ❌ %s)\\n\", \$1, \$2, \$3  }' | sed ':a;N;\$!ba;s/\\n/ | /g'", returnStdout: true).trim()
222         echo "Meridio: $formatted"
223         badge('meridio-e2e-kind-meridio', 'Meridio', formatted)
224     }
225 }
226
227 def ReportTAPA(success, failure) {
228     return {
229         def tapa_success = sh(script: "echo \"$success\" | grep -oP '(?<=TAPA version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s %s 0\\n\", \$2, \$1 }'", returnStdout: true).trim()
230         def tapa_failure = sh(script: "echo \"$failure\" | grep -oP '(?<=TAPA version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s 0 %s\\n\", \$2, \$1 }'", returnStdout: true).trim()
231         def tapa = sh(script: "echo \"$tapa_success\\n$tapa_failure\" | grep -v '^\$' | awk '{ success[\$1] += \$2 ; failure[\$1] += \$3 } END { for(elem in success) print elem, success[elem], failure[elem] }' | sort -k1", returnStdout: true).trim()
232         def formatted = sh(script: "echo \"$tapa\" | awk '{ printf \"%s (✅ %s / ❌ %s)\\n\", \$1, \$2, \$3  }' | sed ':a;N;\$!ba;s/\\n/ | /g'", returnStdout: true).trim()
233         echo "TAPA: $formatted"
234         badge('meridio-e2e-kind-tapa', 'TAPA', formatted)
235     }
236 }
237
238 def ReportNSM(success, failure) {
239     return {
240         def nsm_success = sh(script: "echo \"$success\" | grep -oP '(?<=NSM version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s %s 0\\n\", \$2, \$1 }'", returnStdout: true).trim()
241         def nsm_failure = sh(script: "echo \"$failure\" | grep -oP '(?<=NSM version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s 0 %s\\n\", \$2, \$1 }'", returnStdout: true).trim()
242         def nsm = sh(script: "echo \"$nsm_success\\n$nsm_failure\" | grep -v '^\$' | awk '{ success[\$1] += \$2 ; failure[\$1] += \$3 } END { for(elem in success) print elem, success[elem], failure[elem] }' | sort -k1", returnStdout: true).trim()
243         def formatted = sh(script: "echo \"$nsm\" | awk '{ printf \"%s (✅ %s / ❌ %s)\\n\", \$1, \$2, \$3  }' | sed ':a;N;\$!ba;s/\\n/ | /g'", returnStdout: true).trim()
244         echo "NSM: $formatted"
245         badge('meridio-e2e-kind-nsm', 'NSM', formatted)
246     }
247 }
248
249 def ReportIPFamily(success, failure) {
250     return {
251         def ip_family_success = sh(script: "echo \"$success\" | grep -oP '(?<=IP Family: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s %s 0\\n\", \$2, \$1 }'", returnStdout: true).trim()
252         def ip_family_failure = sh(script: "echo \"$failure\" | grep -oP '(?<=IP Family: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s 0 %s\\n\", \$2, \$1 }'", returnStdout: true).trim()
253         def ip_family = sh(script: "echo \"$ip_family_success\\n$ip_family_failure\" | grep -v '^\$' | awk '{ success[\$1] += \$2 ; failure[\$1] += \$3 } END { for(elem in success) print elem, success[elem], failure[elem] }' | sort -k1", returnStdout: true).trim()
254         def formatted = sh(script: "echo \"$ip_family\" | awk '{ printf \"%s (✅ %s / ❌ %s)\\n\", \$1, \$2, \$3  }' | sed ':a;N;\$!ba;s/\\n/ | /g'", returnStdout: true).trim()
255         echo "IP Family: $formatted"
256         badge('meridio-e2e-kind-ip-family', 'IP Family', formatted)
257     }
258 }
259
260 def ReportKubernetes(success, failure) {
261     return {
262         def kubernetes_success = sh(script: "echo \"$success\" | grep -oP '(?<=Kubernetes version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s %s 0\\n\", \$2, \$1 }'", returnStdout: true).trim()
263         def kubernetes_failure = sh(script: "echo \"$failure\" | grep -oP '(?<=Kubernetes version: ).*?(?=\\/)' | sort | uniq -c | awk '{ printf \"%s 0 %s\\n\", \$2, \$1 }'", returnStdout: true).trim()
264         def kubernetes = sh(script: "echo \"$kubernetes_success\\n$kubernetes_failure\" | grep -v '^\$' | awk '{ success[\$1] += \$2 ; failure[\$1] += \$3 } END { for(elem in success) print elem, success[elem], failure[elem] }' | sort -k1", returnStdout: true).trim()
265         def formatted = sh(script: "echo \"$kubernetes\" | awk '{ printf \"%s (✅ %s / ❌ %s)\\n\", \$1, \$2, \$3  }' | sed ':a;N;\$!ba;s/\\n/ | /g'", returnStdout: true).trim()
266         echo "Kubernetes: $formatted"
267         badge('meridio-e2e-kind-kubernetes', 'Kubernetes', formatted)
268     }
269 }
270
271 def badge(id, subject, message) {
272     addEmbeddableBadgeConfiguration(id: "${id}", subject: "${subject}", color: '#0B1F67', status: "$message")
273     sh """
274     mkdir -p _output
275     echo '{' >> _output/${id}.json
276     echo '"schemaVersion": 1,' >> _output/${id}.json
277     echo '"label": "${subject}",' >> _output/${id}.json
278     echo '"message": "${message}",' >> _output/${id}.json
279     echo '"color": "#0B1F67"' >> _output/${id}.json
280     echo '}' >> _output/${id}.json
281     """
282 }
283
284 // Raise error in Jenkins job
285 def Error(e) {
286     return {
287         Cleanup()
288         error e
289     }
290 }
291
292 // Cleanup directory and kind cluster
293 def Cleanup() {
294     def command = 'make -s -C docs/demo/scripts/kind/ clean'
295     ExecSh(command).call()
296     cleanWs()
297 }
298
299 // Execute command
300 def ExecSh(command) {
301     return {
302         if (env.DRY_RUN != 'true') {
303             sh """
304                 . \${HOME}/.profile
305                 ${command}
306             """
307         } else {
308             echo "${command}"
309         }
310     }
311 }