blob: 2a6499071171ee272e59bfe9b02a72b763522b2f [file] [log] [blame]
chnydae80bb922017-05-29 17:48:40 +02001common = new com.mirantis.mk.Common()
chnydabc63c9a2017-05-30 15:37:54 +02002gerrit = new com.mirantis.mk.Gerrit()
chnydae80bb922017-05-29 17:48:40 +02003git = new com.mirantis.mk.Git()
4python = new com.mirantis.mk.Python()
5saltModelTesting = new com.mirantis.mk.SaltModelTesting()
6
azvyagintsev87985532018-07-10 20:49:38 +03007slave_node = 'python&&docker'
Vasyl Saienko682043d2018-07-23 16:04:10 +03008def reclassVersion = 'v1.5.4'
Vasyl Saienko772e1232018-07-23 14:42:24 +03009if (common.validInputParam('RECLASS_VERSION')) {
10 reclassVersion = RECLASS_VERSION
11}
12
chnyda467f10f2017-05-30 17:25:07 +020013def generateSaltMaster(modEnv, clusterDomain, clusterName) {
azvyagintsev87985532018-07-10 20:49:38 +030014 def nodeFile = "${modEnv}/nodes/cfg01.${clusterDomain}.yml"
15 def nodeString = """classes:
chnydae80bb922017-05-29 17:48:40 +020016- cluster.${clusterName}.infra.config
17parameters:
18 _param:
19 linux_system_codename: xenial
20 reclass_data_revision: master
21 linux:
22 system:
23 name: cfg01
24 domain: ${clusterDomain}
25"""
azvyagintsev87985532018-07-10 20:49:38 +030026 sh "mkdir -p ${modEnv}/nodes/"
27 println "Create file ${nodeFile}"
28 writeFile(file: nodeFile, text: nodeString)
29}
30
31def GetBaseName(line, remove_ext) {
32 filename = line.toString().split('/').last()
33 if (remove_ext && filename.endsWith(remove_ext.toString())) {
34 filename = filename.take(filename.lastIndexOf(remove_ext.toString()))
35 }
36 return filename
chnydae80bb922017-05-29 17:48:40 +020037}
38
chnyda467f10f2017-05-30 17:25:07 +020039def generateModel(modelFile, cutterEnv) {
azvyagintsev87985532018-07-10 20:49:38 +030040 def templateEnv = "${env.WORKSPACE}"
41 def modelEnv = "${env.WORKSPACE}/model"
42 def basename = GetBaseName(modelFile, '.yml')
43 def generatedModel = "${modelEnv}/${basename}"
44 def testEnv = "${env.WORKSPACE}/test"
45 def content = readFile(file: "${templateEnv}/contexts/${modelFile}")
46 def templateContext = readYaml text: content
47 def clusterDomain = templateContext.default_context.cluster_domain
48 def clusterName = templateContext.default_context.cluster_name
49 def outputDestination = "${generatedModel}/classes/cluster/${clusterName}"
50 def targetBranch = "feature/${clusterName}"
51 def templateBaseDir = "${env.WORKSPACE}"
52 def templateDir = "${templateEnv}/dir"
53 def templateOutputDir = templateBaseDir
54 sh(script: "rm -rf ${generatedModel} || true")
chnydae80bb922017-05-29 17:48:40 +020055
azvyagintsev87985532018-07-10 20:49:38 +030056 common.infoMsg("Generating model from context ${modelFile}")
chnydae79b94e2017-07-10 09:46:25 +020057
azvyagintsev87985532018-07-10 20:49:38 +030058 def productList = ["infra", "cicd", "opencontrail", "kubernetes", "openstack", "oss", "stacklight", "ceph"]
59 for (product in productList) {
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020060
azvyagintsev87985532018-07-10 20:49:38 +030061 // get templateOutputDir and productDir
62 if (product.startsWith("stacklight")) {
63 templateOutputDir = "${env.WORKSPACE}/output/stacklight"
64 try {
65 productDir = "stacklight" + templateContext.default_context['stacklight_version']
66 } catch (Throwable e) {
67 productDir = "stacklight1"
68 }
69 } else {
70 templateOutputDir = "${env.WORKSPACE}/output/${product}"
71 productDir = product
chnydae80bb922017-05-29 17:48:40 +020072 }
azvyagintsev87985532018-07-10 20:49:38 +030073
74 if (product == "infra" || (templateContext.default_context["${product}_enabled"]
75 && templateContext.default_context["${product}_enabled"].toBoolean())) {
76
77 templateDir = "${templateEnv}/cluster_product/${productDir}"
78 common.infoMsg("Generating product " + product + " from " + templateDir + " to " + templateOutputDir)
79
80 sh "rm -rf ${templateOutputDir} || true"
81 sh "mkdir -p ${templateOutputDir}"
82 sh "mkdir -p ${outputDestination}"
83
84 python.buildCookiecutterTemplate(templateDir, content, templateOutputDir, cutterEnv, templateBaseDir)
85 sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
86 } else {
87 common.warningMsg("Product " + product + " is disabled")
88 }
89 }
90 generateSaltMaster(generatedModel, clusterDomain, clusterName)
chnydae80bb922017-05-29 17:48:40 +020091}
92
azvyagintsev87985532018-07-10 20:49:38 +030093
Vasyl Saienko682043d2018-07-23 16:04:10 +030094def testModel(modelFile, testEnv, reclassVersion='v1.5.4') {
azvyagintsev87985532018-07-10 20:49:38 +030095 // modelFile - `modelfiname` from model/modelfiname/modelfiname.yaml
96 // testEnv - path for model (model/modelfilename/)
97 //* Grub all models and send it to check in paralell - by one in thread.
chnyda7dd8cd92017-12-18 10:19:25 +010098
azvyagintsev87985532018-07-10 20:49:38 +030099 _values_string = """
100 ---
101 MODELS_TARGZ: "${env.BUILD_URL}/artifact/reclass.tar.gz"
102 DockerCName: "${env.JOB_NAME.toLowerCase()}_${env.BUILD_TAG.toLowerCase()}_${modelFile.toLowerCase()}"
103 testReclassEnv: "model/${modelFile}/"
104 modelFile: "contexts/${modelFile}.yml"
105 DISTRIB_REVISION: "${DISTRIB_REVISION}"
106 EXTRA_FORMULAS: "${env.EXTRA_FORMULAS}"
107 reclassVersion: "${reclassVersion}"
108 """
109 build job: "test-mk-cookiecutter-templates-chunk", parameters: [
110 [$class: 'StringParameterValue', name: 'EXTRA_VARIABLES_YAML', value: _values_string.stripIndent() ],
111 ]
chnydabc63c9a2017-05-30 15:37:54 +0200112}
113
114def gerritRef
115try {
116 gerritRef = GERRIT_REFSPEC
azvyagintsev87985532018-07-10 20:49:38 +0300117 } catch (MissingPropertyException e) {
118 gerritRef = null
119 }
chnydae80bb922017-05-29 17:48:40 +0200120
azvyagintsev87985532018-07-10 20:49:38 +0300121def testModelStep(basename,testEnv) {
122 // We need to wrap what we return in a Groovy closure, or else it's invoked
123 // when this method is called, not when we pass it to parallel.
124 // To do this, you need to wrap the code below in { }, and either return
125 // that explicitly, or use { -> } syntax.
126 return {
127 node(slave_node) {
128 testModel(basename, testEnv)
chnydae80bb922017-05-29 17:48:40 +0200129 }
azvyagintsev87985532018-07-10 20:49:38 +0300130 }
131}
132
133timeout(time: 2, unit: 'HOURS') {
134 node(slave_node) {
135 def templateEnv = "${env.WORKSPACE}"
136 def cutterEnv = "${env.WORKSPACE}/cutter"
137 def jinjaEnv = "${env.WORKSPACE}/jinja"
138
139 try {
140 // Fixme. Just use 'cleanup workspace' option.
141 stage("Cleanup") {
142 sh(script: 'find . -mindepth 1 -delete > /dev/null || true')
143 }
144
145 stage('Download Cookiecutter template') {
146 if (gerritRef) {
147 def gerritChange = gerrit.getGerritChange(GERRIT_NAME, GERRIT_HOST, GERRIT_CHANGE_NUMBER, CREDENTIALS_ID)
148 merged = gerritChange.status == "MERGED"
149 if (!merged) {
150 checkouted = gerrit.gerritPatchsetCheckout([
151 credentialsId: CREDENTIALS_ID
152 ])
153 } else {
154 common.successMsg("Change ${GERRIT_CHANGE_NUMBER} is already merged, no need to gate them")
155 }
156 } else {
157 git.checkoutGitRepository(templateEnv, COOKIECUTTER_TEMPLATE_URL, COOKIECUTTER_TEMPLATE_BRANCH, CREDENTIALS_ID)
158 }
159 }
160
161 stage("Setup") {
162 python.setupCookiecutterVirtualenv(cutterEnv)
163 }
164
165 stage("Check workflow_definition") {
166 sh(script: "python ${env.WORKSPACE}/workflow_definition_test.py")
167 }
168
169 def contextFileList = []
170 dir("${templateEnv}/contexts") {
171 for (String x : findFiles(glob: "*.yml")) {
172 contextFileList.add(x)
173 }
174 }
175
176 stage("generate-model") {
177 for (contextFile in contextFileList) {
178 generateModel(contextFile, cutterEnv)
179 }
180 }
181
182 dir("${env.WORKSPACE}") {
183 // Collect only models. For backward compatability - who know, probably someone use it..
184 sh(script: "tar -czf model.tar.gz -C model ../contexts .", returnStatus: true)
185 archiveArtifacts artifacts: "model.tar.gz"
186 // to be able share reclass for all subenvs
187 // Also, makes artifact test more solid - use one reclass for all of sub-models.
188 // Archive Structure will be:
189 // tar.gz
190 // ├── contexts
191 // │   └── ceph.yml
192 // ├── global_reclass <<< reclass system
193 // ├── model
194 // │   └── ceph <<< from `context basename`
195 // │   ├── classes
196 // │   │   ├── cluster
197 // │   │   └── system -> ../../../global_reclass
198 // │   └── nodes
199 // │   └── cfg01.ceph-cluster-domain.local.yml
200
201 if (SYSTEM_GIT_URL == "") {
202 git.checkoutGitRepository("${env.WORKSPACE}/global_reclass/", RECLASS_MODEL_URL, RECLASS_MODEL_BRANCH, CREDENTIALS_ID)
203 } else {
204 dir("${env.WORKSPACE}/global_reclass/") {
205 if (!gerrit.gerritPatchsetCheckout(SYSTEM_GIT_URL, SYSTEM_GIT_REF, "HEAD", CREDENTIALS_ID)) {
206 common.errorMsg("Failed to obtain system reclass with url: ${SYSTEM_GIT_URL} and ${SYSTEM_GIT_REF}")
207 throw new RuntimeException("Failed to obtain system reclass")
208 }
209 }
210 }
211 // link all models, to use one global reclass
212 for (String context : contextFileList) {
213 def basename = GetBaseName(context, '.yml')
214 dir("${env.WORKSPACE}/model/${basename}"){
215 sh(script: 'mkdir -p classes/; ln -sfv ../../../global_reclass classes/system ')
216 }
217 }
218 // Save all models and all contexts. Warning! `h` flag has been used.
219 sh(script: "tar -chzf reclass.tar.gz --exclude='*@tmp' model contexts global_reclass", returnStatus: true)
220 archiveArtifacts artifacts: "reclass.tar.gz"
221 }
222
223 stage("test-contexts") {
224 stepsForParallel = [:]
225 common.infoMsg("Found: ${contextFileList.size()} contexts to test.")
226 for (String context : contextFileList) {
227 def basename = GetBaseName(context, '.yml')
228 def testEnv = "${env.WORKSPACE}/model/${basename}"
229 stepsForParallel.put("Test:${basename}", testModelStep(basename, testEnv))
230 }
231 parallel stepsForParallel
232 common.infoMsg('All tests done')
233 }
234
235 stage('Clean workspace directories') {
236 sh(script: 'find . -mindepth 1 -delete > /dev/null || true')
237 }
238
239} catch (Throwable e) {
240 currentBuild.result = "FAILURE"
241 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
242 throw e
243 } finally {
244 def dummy = "dummy"
245 //FAILING common.sendNotification(currentBuild.result,"",["slack"])
246 }
247 }
chnydae80bb922017-05-29 17:48:40 +0200248}