add ccsdk-sli-northbound
[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().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() {
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         try {
203             archiveArtifacts artifacts: '_output/**/*.*', followSymlinks: false
204         } catch (Exception e) {
205         }
206     }
207 }
208
209 def ReportMeridio(success, failure) {
210     return {
211         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()
212         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()
213         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()
214         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()
215         echo "Meridio: $formatted"
216         badge('meridio-e2e-kind-meridio', 'Meridio', formatted)
217     }
218 }
219
220 def ReportTAPA(success, failure) {
221     return {
222         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()
223         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()
224         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()
225         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()
226         echo "TAPA: $formatted"
227         badge('meridio-e2e-kind-tapa', 'TAPA', formatted)
228     }
229 }
230
231 def ReportNSM(success, failure) {
232     return {
233         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()
234         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()
235         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()
236         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()
237         echo "NSM: $formatted"
238         badge('meridio-e2e-kind-nsm', 'NSM', formatted)
239     }
240 }
241
242 def ReportIPFamily(success, failure) {
243     return {
244         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()
245         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()
246         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()
247         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()
248         echo "IP Family: $formatted"
249         badge('meridio-e2e-kind-ip-family', 'IP Family', formatted)
250     }
251 }
252
253 def ReportKubernetes(success, failure) {
254     return {
255         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()
256         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()
257         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()
258         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()
259         echo "Kubernetes: $formatted"
260         badge('meridio-e2e-kind-kubernetes', 'Kubernetes', formatted)
261     }
262 }
263
264 def badge(id, subject, message) {
265     addEmbeddableBadgeConfiguration(id: "${id}", subject: "${subject}", color: '#0B1F67', status: "$message")
266     sh """
267     mkdir -p _output
268     echo '{' >> _output/${id}.json
269     echo '"schemaVersion": 1,' >> _output/${id}.json
270     echo '"label": "${subject}",' >> _output/${id}.json
271     echo '"message": "${message}",' >> _output/${id}.json
272     echo '"color": "#0B1F67"' >> _output/${id}.json
273     echo '}' >> _output/${id}.json
274     """
275 }
276
277 // Raise error in Jenkins job
278 def Error(e) {
279     return {
280         Cleanup()
281         error e
282     }
283 }
284
285 // Cleanup directory and kind cluster
286 def Cleanup() {
287     def command = 'make -s -C docs/demo/scripts/kind/ clean'
288     ExecSh(command).call()
289     cleanWs()
290 }
291
292 // Execute command
293 def ExecSh(command) {
294     return {
295         if (env.DRY_RUN != 'true') {
296             sh """
297                 . \${HOME}/.profile
298                 ${command}
299             """
300         } else {
301             echo "${command}"
302         }
303     }
304 }