Merge "Meridio: Fix e2e report and better error handling"
[infra/cicd.git] / jjb / nsm / e2e.Jenkinsfile
1 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
2
3 node('nordix-nsm-build-ubuntu1804') {
4     build_number = env.BUILD_NUMBER
5     workspace = env.WORKSPACE
6     ws("${workspace}/${build_number}") {
7         def git_project = params.GIT_PROJECT
8         def current_branch = params.CURRENT_BRANCH
9         def default_branch = params.DEFAULT_BRANCH
10         def next = params.NEXT
11
12         def meridio_version = params.MERIDIO_VERSION
13         def tapa_version = params.TAPA_VERSION
14         def kubernetes_version = params.KUBERNETES_VERSION
15         def nsm_version = params.NSM_VERSION
16         def ip_family = params.IP_FAMILY
17
18         stage('Clone/Checkout') {
19             git branch: default_branch, url: git_project
20             checkout([
21                 $class: 'GitSCM',
22                 branches: [[name: current_branch]],
23                 extensions: [],
24                 userRemoteConfigs: [[
25                     refspec: '+refs/pull/*/head:refs/remotes/origin/pr/*',
26                     url: git_project
27                 ]]
28             ])
29             sh 'git show'
30         }
31         timeout(60) {
32             stage('Environment') {
33                 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"
34
35                 try {
36                     ExecSh("make -s -C docs/demo/scripts/kind/ KUBERNETES_VERSION=$kubernetes_version NSM_VERSION=$nsm_version KUBERNETES_IP_FAMILY=$ip_family").call()
37                     ExecSh("helm install deployments/helm/ --generate-name --create-namespace --namespace red --set trench.name=trench-a --set ipFamily=$ip_family").call()
38                     ExecSh("helm install deployments/helm/ --generate-name --create-namespace --namespace red --set trench.name=trench-b --set vlan.id=200 --set ipFamily=$ip_family").call()
39                     ExecSh('helm install examples/target/deployments/helm/ --generate-name --create-namespace --namespace red --set applicationName=target-a --set default.trench.name=trench-a').call()
40                     ExecSh('helm install examples/target/deployments/helm/ --generate-name --create-namespace --namespace red --set applicationName=target-b --set default.trench.name=trench-b').call()
41                     sh 'sleep 10'
42                     ExecSh('kubectl wait --for=condition=Ready pods --all --all-namespaces --timeout=5m').call()
43                 } catch (Exception e) {
44                     Error('Error creating the environment').call()
45                 }
46             }
47             stage('E2E') {
48                 try {
49                     ExecSh("make e2e E2E_PARAMETERS=\"\$(cat ./test/e2e/environment/kind-helm/$ip_family/config.txt | tr '\\n' ' ')\"").call()
50                 } catch (Exception e) {
51                     unstable 'E2E Tests failed'
52                     currentBuild.result = 'FAILURE'
53                 }
54             }
55         }
56         stage('Cleanup') {
57             Cleanup()
58         }
59         stage('Report') {
60             Report().call()
61         }
62         stage('Next') {
63             Next(next).call()
64         }
65     }
66 }
67
68 def Next(next) {
69     if (next == 'true') {
70         return {
71             def meridio_version = GetMeridioVersion()
72             def tapa_version = GetTAPAVersion()
73             def nsm_version = GetNSMVersion()
74             def kubernetes_version = GetKubernetesVersion()
75             def ip_family = GetIPFamily()
76             echo "Meridio version: $meridio_version / TAPA version: $tapa_version / NSM version: $nsm_version / IP Family: $ip_family / Kubernetes version: $kubernetes_version"
77             build job: 'meridio-e2e-test-kind', parameters: [
78                 string(name: 'NEXT', value: 'true'),
79                 string(name: 'MERIDIO_VERSION', value: "$meridio_version"),
80                 string(name: 'TAPA_VERSION', value: "$tapa_version"),
81                 string(name: 'KUBERNETES_VERSION', value: "$kubernetes_version"),
82                 string(name: 'NSM_VERSION', value: "$nsm_version"),
83                 string(name: 'IP_FAMILY', value: "$ip_family")
84             ], wait: false
85         }
86     } else {
87         return {
88             Utils.markStageSkippedForConditional('Next')
89         }
90     }
91 }
92
93 def GetMeridioVersion() {
94     def number_of_versions = sh(script: 'cat test/e2e/environment/kind-helm/test-scope.yaml | yq ".Meridio[]" | wc -l', returnStdout: true).trim()
95     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
96     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
97     return sh(script: "cat test/e2e/environment/kind-helm/test-scope.yaml | yq '.Meridio[$index_of_version]'", returnStdout: true).trim()
98 }
99
100 def GetTAPAVersion() {
101     def number_of_versions = sh(script: 'cat test/e2e/environment/kind-helm/test-scope.yaml | yq ".TAPA[]" | wc -l', returnStdout: true).trim()
102     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
103     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
104     return sh(script: "cat test/e2e/environment/kind-helm/test-scope.yaml | yq '.TAPA[$index_of_version]'", returnStdout: true).trim()
105 }
106
107 def GetNSMVersion() {
108     def number_of_versions = sh(script: 'cat test/e2e/environment/kind-helm/test-scope.yaml | yq ".NSM[]" | wc -l', returnStdout: true).trim()
109     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
110     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
111     return sh(script: "cat test/e2e/environment/kind-helm/test-scope.yaml | yq '.NSM[$index_of_version]'", returnStdout: true).trim()
112 }
113
114 def GetKubernetesVersion() {
115     def number_of_versions = sh(script: 'cat test/e2e/environment/kind-helm/test-scope.yaml | yq ".Kubernetes[]" | wc -l', returnStdout: true).trim()
116     def index_of_version_temp = sh(script: "shuf -i 1-$number_of_versions -n1", returnStdout: true).trim()
117     def index_of_version = sh(script: "expr $index_of_version_temp - 1 || true", returnStdout: true).trim()
118     return sh(script: "cat test/e2e/environment/kind-helm/test-scope.yaml | yq '.Kubernetes[$index_of_version]'", returnStdout: true).trim()
119 }
120
121 def GetIPFamily() {
122     def number_of_ip_family = sh(script: 'cat test/e2e/environment/kind-helm/test-scope.yaml | yq ".IP-Family[]" | wc -l', returnStdout: true).trim()
123     def index_of_ip_family_temp = sh(script: "shuf -i 1-$number_of_ip_family -n1", returnStdout: true).trim()
124     def index_of_ip_family = sh(script: "expr $index_of_ip_family_temp - 1 || true", returnStdout: true).trim()
125     return sh(script: "cat test/e2e/environment/kind-helm/test-scope.yaml | yq '.IP-Family[$index_of_ip_family]'", returnStdout: true).trim()
126 }
127
128 // http://JENKINS_URL/job/meridio-e2e-test-kind/api/json?tree=allBuilds[status,timestamp,id,result,description]{0,9}&pretty=true
129 def Report() {
130     return {
131         def jenkins_url = 'jenkins.nordix.org'
132
133         def success = ''
134         try {
135             success = sh(script: """
136             data=\$(curl -s -L "http://$jenkins_url/job/meridio-e2e-test-kind/api/json?tree=allBuilds\\[status,timestamp,id,result,description\\]\\{0,999\\}&pretty=true")
137             success=\$(echo \"\$data\" | jq -r '.allBuilds[] | select(.result == \"SUCCESS\") | [.description] | @tsv' | grep -v \"^\$\")
138             echo \$success
139             """, returnStdout: true).trim()
140         } catch (Exception e) {
141         }
142
143         def failure = ''
144         try {
145             failure = sh(script: """
146             data=\$(curl -s -L "http://$jenkins_url/job/meridio-e2e-test-kind/api/json?tree=allBuilds\\[status,timestamp,id,result,description\\]\\{0,999\\}&pretty=true")
147             failure=\$(echo \"\$data\" | jq -r '.allBuilds[] | select(.result == \"FAILURE\") | [.description] | @tsv' | grep -v \"^\$\")
148             echo \$failure
149             """, returnStdout: true).trim()
150         } catch (Exception e) {
151         }
152
153         ReportMeridio(success, failure).call()
154         ReportTAPA(success, failure).call()
155         ReportNSM(success, failure).call()
156         ReportIPFamily(success, failure).call()
157         ReportKubernetes(success, failure).call()
158     }
159 }
160
161 def ReportMeridio(success, failure) {
162     return {
163         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()
164         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()
165         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()
166         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()
167         echo "Meridio: $formatted"
168         def meridio_badge = addEmbeddableBadgeConfiguration(id: 'meridio-e2e-kind-meridio', subject: 'Meridio', color: '#0B1F67', status: "$formatted")
169     }
170 }
171
172 def ReportTAPA(success, failure) {
173     return {
174         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()
175         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()
176         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()
177         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()
178         echo "TAPA: $formatted"
179         def tapa_badge = addEmbeddableBadgeConfiguration(id: 'meridio-e2e-kind-tapa', subject: 'TAPA', color: '#0B1F67', status: "$formatted")
180     }
181 }
182
183 def ReportNSM(success, failure) {
184     return {
185         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()
186         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()
187         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()
188         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()
189         echo "NSM: $formatted"
190         def nsm_badge = addEmbeddableBadgeConfiguration(id: 'meridio-e2e-kind-nsm', subject: 'NSM', color: '#0B1F67', status: "$formatted")
191     }
192 }
193
194 def ReportIPFamily(success, failure) {
195     return {
196         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()
197         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()
198         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()
199         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()
200         echo "IP Family: $formatted"
201         def ip_family_badge = addEmbeddableBadgeConfiguration(id: 'meridio-e2e-kind-ip-family', subject: 'IP Family', color: '#0B1F67', status: "$formatted")
202     }
203 }
204
205 def ReportKubernetes(success, failure) {
206     return {
207         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()
208         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()
209         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()
210         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()
211         echo "Kubernetes: $formatted"
212         def kubernetes_badge = addEmbeddableBadgeConfiguration(id: 'meridio-e2e-kind-kubernetes', subject: 'Kubernetes', color: '#0B1F67', status: "$formatted")
213     }
214 }
215
216 // Raise error in Jenkins job
217 def Error(e) {
218     return {
219         Cleanup()
220         error e
221     }
222 }
223
224 // Cleanup directory and kind cluster
225 def Cleanup() {
226     ExecSh('make -s -C docs/demo/scripts/kind/ clean').call()
227     cleanWs()
228 }
229
230 // Execute command
231 def ExecSh(command) {
232     return {
233         sh """
234             . \${HOME}/.profile
235             ${command}
236         """
237     }
238 }