Browse Source

Redesign tamarin and vulcain API

nebula
William Petit 5 months ago
parent
commit
ff1b1f148d
4 changed files with 232 additions and 22 deletions
  1. 17
    4
      README.md
  2. 186
    0
      pipelines/debian-packaging.jenkinsfile
  3. 24
    12
      vars/tamarin.groovy
  4. 5
    6
      vars/vulcain.groovy

+ 17
- 4
README.md View File

@@ -1,18 +1,31 @@
1 1
 # Jenkins
2 2
 
3
-Librairie utilitaire pour la création de pipeline Jenkins dans l'environnement Cadoles.
3
+Utilitaires pour la création de pipeline Jenkins dans l'environnement Cadoles.
4 4
 
5
-## Méthodes exposées
5
+## Pipelines
6 6
 
7
-### Création de paquets
7
+- [Pipeline d'empaquetage Debian](./pipelines/debian-packaging.jenkinsfile)
8
+
9
+## Librairie
10
+
11
+### Méthodes exposées
12
+
13
+#### Création de paquets
8 14
 
9 15
 - [`tamarin.buildPackage()`](./vars/tamarin.groovy#L48)
10 16
 - [`tamarin.buildPackageWithCPKG()`](./vars/tamarin.groovy#L1)
11 17
 
12
-### Publication de paquets
18
+#### Publication de paquets
13 19
 
14 20
 - [`vulcain.publish()`](./vars/vulcain.groovy#L1)
15 21
 
22
+#### Pilotage d'OpenNebula
23
+
24
+- [`nebula.initWithCredentials()`](./vars/nebula.groovy#L125)
25
+- [`nebula.runInNewVM() { client -> ... }`](./vars/nebula.groovy#L135)
26
+- [`client.findVMTemplate()`](./vars/nebula.groovy#L65)
27
+- [`client.withNewVM()`](./vars/nebula.groovy#L79)
28
+
16 29
 ## Licence
17 30
 
18 31
 GPL-3.0

+ 186
- 0
pipelines/debian-packaging.jenkinsfile View File

@@ -0,0 +1,186 @@
1
+@Library("cadoles") _
2
+
3
+pipeline {
4
+
5
+    agent {
6
+        label 'common'
7
+    }
8
+    
9
+    environment {
10
+        projectDir = "${env.project_name}_${env.BUILD_ID}" 
11
+    }
12
+
13
+    stages {
14
+      
15
+        stage("Clone repository") {
16
+            steps {
17
+                checkout scm: 
18
+                    [
19
+                        $class: 'GitSCM', 
20
+                        userRemoteConfigs: [[url: env.repository_url, credentialsId: 'forge-jenkins']], 
21
+                        branches: [[name: env.ref]],
22
+                        extensions: [
23
+                            [$class: 'RelativeTargetDirectory', relativeTargetDir: env.projectDir ],
24
+                            [$class: 'CloneOption', noTags: false, shallow: false, depth: 0, reference: ''],
25
+                            [$class: 'WipeWorkspace' ]
26
+                        ]
27
+                    ], 
28
+                    changelog: false, 
29
+                    poll: false
30
+            }
31
+        }
32
+        
33
+        stage("Ensure packaging branch") {
34
+            steps {
35
+                script {
36
+                    dir(env.projectDir) {
37
+                        sh 'git checkout "${packageBranch}"'
38
+                        def commitOrRef = env.commit ? env.commit : env.ref
39
+                        def branchesWithCommitOrRef = sh(script: "git branch --contains '${commitOrRef}'", returnStdout: true).split(' ')
40
+                        if (branchesWithCommitOrRef.findAll{env.packageBranch.contains(it)}.any{true}) {
41
+                            currentBuild.result = 'ABORTED'
42
+                            error("La référence `${env.ref}` ne fait pas partie de la branche `${env.packageBranch}` !")
43
+                        }
44
+                    }
45
+                }
46
+            }
47
+        }
48
+        
49
+         stage("Checkout ref") {
50
+            steps {
51
+                dir(env.projectDir) {
52
+                    sh """
53
+                    git checkout ${env.ref}
54
+                    """
55
+                }
56
+            }
57
+        }
58
+    
59
+        stage("Build package") {
60
+            steps {
61
+                script {
62
+                    dir(env.projectDir) {
63
+                        
64
+                        // On construit les paquets à partir des informations
65
+                        // de contexte provenant de CPKG et du webhook
66
+                        def result = tamarin.buildPackageWithCPKG(
67
+                            env.packageProfile ? env.packageProfile : "debian",
68
+                            env.packageArch ? env.packageArch : "",
69
+                            env.packageBranch ? env.packageBranch : "",
70
+                            env.baseImage ? env.baseImage : ""
71
+                        )
72
+                        
73
+                        // On publie chacun des paquets construits
74
+                        result.each { r ->
75
+                            vulcain.publish(
76
+                                r.packages,
77
+                                r.env,
78
+                                env.packageBranch
79
+                            )
80
+                        }
81
+                        
82
+                        // On liste l'ensemble des paquets construits
83
+                        def publishedPackages = result.collect { r ->
84
+                            return r.packages.collect { p ->
85
+                                def file = new File(p)
86
+                                return "- Paquet `${file.getName()}`, Dépôt `${r.env}`, Distribution `${r.distrib}`"
87
+                            }
88
+                        }.transpose().collectMany { it }
89
+                        
90
+                        // On notifie le canal Rocket.Chat de la publication des paquets
91
+                        rocketSend (
92
+                            avatar: 'https://jenkins.cadol.es/static/b5f67753/images/headshot.png',
93
+                            message: """
94
+                            Les paquets suivants ont été publiés pour le projet ${env.project_name}:
95
+                            
96
+                            ${publishedPackages.join('\n')}
97
+                    
98
+                            [Visualiser le job](${env.RUN_DISPLAY_URL})
99
+                            
100
+                            @${env.sender_login}
101
+                            """.stripIndent(),
102
+                            rawMessage: true
103
+                        )
104
+
105
+                        if (env.testPackageInstall == 'no') {
106
+                            println "Test d'intallation des paquets désactivé."
107
+                            return
108
+                        }
109
+                        
110
+                        // Pour chaque construction de paquets...
111
+                        result.each { r ->
112
+
113
+                            // On essaye de trouver un template de VM compatible
114
+                            // avec la distribution cible de la construction
115
+                            def vmTemplate = findMatchingVMTemplate(r.distrib)
116
+                            if (vmTemplate == null) {
117
+                                println "Aucun template de VM n'a été trouvé correspondant à la distribution `${r.distrib}`."
118
+                                return
119
+                            }
120
+
121
+                            // Pour chaque paquets construits...
122
+                            r.packages.each { p ->
123
+                                def packageName = new File(p).getName()
124
+                                stage("Test package '${packageName}' installation") {
125
+                                    try {
126
+                                        // On démarre une nouvelle VM et on lance l'installation du paquet publié
127
+                                        testPackageInstallation(vmTemplate, r.distrib, r.env, packageName)
128
+                                    } catch(e) {
129
+                                        currentBuild.result = 'UNSTABLE'
130
+                                        rocketSend (
131
+                                            avatar: 'https://jenkins.cadol.es/static/b5f67753/images/headshot.png',
132
+                                            message: """
133
+                                            [Installation du paquet `${packageName}` échouée sur `${vmTemplate}`](${env.RUN_DISPLAY_URL})
134
+                                            
135
+                                            @${env.sender_login}
136
+                                            """.stripIndent(),
137
+                                            rawMessage: true
138
+                                        )
139
+                                        error("Installation du paquet `${packageName}` échouée.")
140
+                                    }
141
+                                }
142
+                            }
143
+                        }
144
+                        
145
+                    }
146
+                }
147
+            }
148
+        }
149
+
150
+    }
151
+    
152
+    post {
153
+        always {
154
+            sh "rm -rf '${env.projectDir}'"
155
+        }
156
+    }
157
+
158
+}
159
+
160
+// Cette fonction fait un simple "mapping"
161
+// entre les distributions cibles des paquets et
162
+// les templates de VM disponibles sur l'OpenNebula
163
+def findMatchingVMTemplate(String distrib) {
164
+    def vmTemplatesMap = [
165
+        'eole-2.7.0': 'eolebase-2.7.0-cadoles',
166
+        'eole-2.6.2': 'eolebase-2.6.2-cadoles'
167
+    ]
168
+    return vmTemplatesMap.get(distrib, null)
169
+}
170
+
171
+// Cette fonction démarre une nouvelle VM, configure les dépôts tiers pour ajouter
172
+// celui de Cadoles correspondant à la cible du paquet et tente d'installer celui ci.
173
+def testPackageInstallation(String vmTemplate, String distrib, String env, String packageName) {
174
+    def version = distrib.split('-')[1]
175
+    def packageNameParts = packageName.split('_')
176
+    nebula.runInNewVM([
177
+        vmTemplate: vmTemplate,
178
+        script: """
179
+        set -xeo pipefail
180
+        wget -qO - https://vulcain.cadoles.com/cadoles.gpg | apt-key add -
181
+        echo 'deb https://vulcain.cadoles.com ${version}-${env} main' > /etc/apt/sources.list.d/${version}-${env}.list
182
+        apt-get update -y
183
+        apt-get install -y ${packageNameParts[0]}=${packageNameParts[1]}
184
+        """
185
+    ])
186
+}

+ 24
- 12
vars/tamarin.groovy View File

@@ -4,10 +4,11 @@ def buildPackageWithCPKG(
4 4
     String packageBranch = "",
5 5
     String baseImage = "", 
6 6
     String destDir = "./packages",
7
-    Boolean forceRebuild = false,
8
-    Boolean publishPackages = true
7
+    Boolean forceRebuild = false
9 8
 ) {
10 9
 
10
+    def builds = []
11
+
11 12
     // Retrieve commit tags
12 13
     def commitTags = sh(script: 'git describe --exact-match --abbrev=0', returnStdout: true).split(' ')
13 14
     if (commitTags.length == 0) {
@@ -30,20 +31,23 @@ def buildPackageWithCPKG(
30 31
         """.stripIndent()
31 32
         writeFile file: '.tamarinrc', text: tamarinrc
32 33
         
34
+        sh "rm -rf ${destDir}/*"
35
+
33 36
         stage("Build ${packageEnv} package (version ${packageVersion}) for ${packageDistrib}") {
34
-            
35
-            sh "rm -rf ${destDir}/*"
36
-            buildPackage(packageProfile, packageArch, baseImage, destDir, forceRebuild)
37
-            
38
-            if (publishPackages) {
39
-                stage("Publish ${packageEnv} packages (version ${packageVersion}) on Vulcain") {
40
-                    vulcain.publish(destDir, packageEnv, packageBranch)
41
-                }
42
-            }
37
+            def result = [:]
38
+            result.put('tag', tag)
39
+            result.put('env', packageEnv)
40
+            result.put('version', packageVersion)
41
+            result.put('distrib', packageDistrib)
42
+            def packages = buildPackage(packageProfile, packageArch, baseImage, destDir, forceRebuild)
43
+            result.put('packages', packages)
44
+            builds << result
43 45
         }
44 46
         
45 47
     }
46 48
 
49
+    return builds
50
+
47 51
 }
48 52
 
49 53
 def buildPackage(
@@ -54,7 +58,8 @@ def buildPackage(
54 58
     Boolean forceRebuild = false
55 59
 ) {
56 60
 
57
-    def tamarinImage 
61
+    def tamarinImage
62
+    def packages = []
58 63
     
59 64
     stage("Create Tamarin environment") {
60 65
         tamarinImage = buildDockerImage()
@@ -73,7 +78,14 @@ def buildPackage(
73 78
         tamarinImage.inside(dockerArgs) {
74 79
             sh 'run-tamarin'
75 80
         }
81
+
82
+        packages = sh(script: "find '${destDir}' -name '*.deb' -type f", returnStdout: true)
83
+            .split(' ')
84
+            .collect { return it.trim() }
85
+            .findAll { it != '' }
76 86
     }
87
+
88
+    return packages
77 89
     
78 90
 }
79 91
 

+ 5
- 6
vars/vulcain.groovy View File

@@ -1,5 +1,5 @@
1 1
 def publish(
2
-    String packagesDir = './packages', 
2
+    List packages = [], 
3 3
     String packagesEnv = 'dev', 
4 4
     String packagesBranch = '',
5 5
     String sshCredentialsId = 'vulcain-packages-ssh-keypair',
@@ -8,14 +8,13 @@ def publish(
8 8
     if (!packagesBranch) {
9 9
         packagesBranch = env.BRANCH_NAME
10 10
     }
11
-    
12 11
     withCredentials([
13 12
         sshUserPrivateKey(credentialsId: sshCredentialsId, keyFileVariable: 'VULCAIN_SSH_KEY', usernameVariable: 'VULCAIN_SSH_USER')
14 13
     ]) {
15 14
         echo "Publishing packages to '${packagesEnv}/${packagesBranch}'"
16
-        sh """
17
-        ssh -i '${VULCAIN_SSH_KEY}' -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '${VULCAIN_SSH_USER}@${vulcainHost}' mkdir -p '/home/${VULCAIN_SSH_USER}/packages/${packagesEnv}/${packagesBranch}'
18
-        scp -i '${VULCAIN_SSH_KEY}' -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r ${packagesDir}/*.deb '${VULCAIN_SSH_USER}@${vulcainHost}:/home/${VULCAIN_SSH_USER}/packages/${packagesEnv}/${packagesBranch}/'
19
-        """
15
+        sh "ssh -i '${VULCAIN_SSH_KEY}' -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '${VULCAIN_SSH_USER}@${vulcainHost}' mkdir -p '/home/${VULCAIN_SSH_USER}/packages/${packagesEnv}/${packagesBranch}'"
16
+        packages.each {
17
+            sh "scp -i '${VULCAIN_SSH_KEY}' -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '${it}' '${VULCAIN_SSH_USER}@${vulcainHost}:/home/${VULCAIN_SSH_USER}/packages/${packagesEnv}/${packagesBranch}/'"
18
+        }
20 19
     }
21 20
 }

Loading…
Cancel
Save