blob: d11f7d4285f6bd95a5a6f110a3fd5999a186616f [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
Vasyl Saienko772e1232018-07-23 14:42:24 +03007def reclassVersion = '1.5.4'
8if (common.validInputParam('RECLASS_VERSION')) {
9 reclassVersion = RECLASS_VERSION
10}
11
chnyda467f10f2017-05-30 17:25:07 +020012def generateSaltMaster(modEnv, clusterDomain, clusterName) {
13 def nodeFile = "${modEnv}/nodes/cfg01.${clusterDomain}.yml"
chnydae80bb922017-05-29 17:48:40 +020014 def nodeString = """classes:
15- cluster.${clusterName}.infra.config
16parameters:
17 _param:
18 linux_system_codename: xenial
19 reclass_data_revision: master
20 linux:
21 system:
22 name: cfg01
23 domain: ${clusterDomain}
24"""
chnyda467f10f2017-05-30 17:25:07 +020025 sh "mkdir -p ${modEnv}/nodes/"
26 println "Create file ${nodeFile}"
chnydae80bb922017-05-29 17:48:40 +020027 writeFile(file: nodeFile, text: nodeString)
28}
29
chnyda467f10f2017-05-30 17:25:07 +020030def generateModel(modelFile, cutterEnv) {
chnydabc63c9a2017-05-30 15:37:54 +020031 def templateEnv = "${env.WORKSPACE}"
32 def modelEnv = "${env.WORKSPACE}/model"
chnyda467f10f2017-05-30 17:25:07 +020033 def basename = sh(script: "basename ${modelFile} .yml", returnStdout: true).trim()
chnydabc63c9a2017-05-30 15:37:54 +020034 def generatedModel = "${modelEnv}/${basename}"
35 def testEnv = "${env.WORKSPACE}/test"
chnyda467f10f2017-05-30 17:25:07 +020036 def content = readFile(file: "${templateEnv}/contexts/${modelFile}")
chnydabc63c9a2017-05-30 15:37:54 +020037 def templateContext = readYaml text: content
chnydae80bb922017-05-29 17:48:40 +020038 def clusterDomain = templateContext.default_context.cluster_domain
39 def clusterName = templateContext.default_context.cluster_name
chnydabc63c9a2017-05-30 15:37:54 +020040 def outputDestination = "${generatedModel}/classes/cluster/${clusterName}"
chnydae80bb922017-05-29 17:48:40 +020041 def targetBranch = "feature/${clusterName}"
chnydabc63c9a2017-05-30 15:37:54 +020042 def templateBaseDir = "${env.WORKSPACE}"
43 def templateDir = "${templateEnv}/dir"
chnydae80bb922017-05-29 17:48:40 +020044 def templateOutputDir = templateBaseDir
chnydabc63c9a2017-05-30 15:37:54 +020045 sh "rm -rf ${generatedModel} || true"
chnydae80bb922017-05-29 17:48:40 +020046
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020047 common.infoMsg("Generating model from context ${modelFile}")
chnydae79b94e2017-07-10 09:46:25 +020048
Mikhail Ivanov30c91f42017-11-07 20:42:26 +040049 def productList = ["infra", "cicd", "opencontrail", "kubernetes", "openstack", "oss", "stacklight", "ceph"]
chnyda467f10f2017-05-30 17:25:07 +020050 for (product in productList) {
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020051
52 // get templateOutputDir and productDir
53 if (product.startsWith("stacklight")) {
54 templateOutputDir = "${env.WORKSPACE}/output/stacklight"
55 try {
56 productDir = "stacklight" + templateContext.default_context['stacklight_version']
57 } catch (Throwable e) {
58 productDir = "stacklight1"
59 }
60 } else {
61 templateOutputDir = "${env.WORKSPACE}/output/${product}"
62 productDir = product
63 }
64
chnyda467f10f2017-05-30 17:25:07 +020065 if (product == "infra" || (templateContext.default_context["${product}_enabled"]
66 && templateContext.default_context["${product}_enabled"].toBoolean())) {
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020067
68 templateDir = "${templateEnv}/cluster_product/${productDir}"
69 common.infoMsg("Generating product " + product + " from " + templateDir + " to " + templateOutputDir)
70
chnyda467f10f2017-05-30 17:25:07 +020071 sh "rm -rf ${templateOutputDir} || true"
72 sh "mkdir -p ${templateOutputDir}"
73 sh "mkdir -p ${outputDestination}"
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020074
chnyda467f10f2017-05-30 17:25:07 +020075 python.buildCookiecutterTemplate(templateDir, content, templateOutputDir, cutterEnv, templateBaseDir)
76 sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020077 } else {
78 common.warningMsg("Product " + product + " is disabled")
chnydae80bb922017-05-29 17:48:40 +020079 }
80 }
chnyda467f10f2017-05-30 17:25:07 +020081 generateSaltMaster(generatedModel, clusterDomain, clusterName)
chnydae80bb922017-05-29 17:48:40 +020082}
83
chnyda467f10f2017-05-30 17:25:07 +020084def testModel(modelFile, testEnv) {
azvyagintsev7c4a3cf2018-07-08 08:43:33 +030085 def templateEnv = "${env.WORKSPACE}"
86 def content = readFile(file: "${templateEnv}/contexts/${modelFile}.yml")
87 def templateContext = readYaml text: content
88 def clusterName = templateContext.default_context.cluster_name
89 def clusterDomain = templateContext.default_context.cluster_domain
90 if (SYSTEM_GIT_URL == "") {
91 git.checkoutGitRepository("${testEnv}/classes/system", RECLASS_MODEL_URL, RECLASS_MODEL_BRANCH, CREDENTIALS_ID)
92 } else {
93 dir("${testEnv}/classes/system") {
94 if (!gerrit.gerritPatchsetCheckout(SYSTEM_GIT_URL, SYSTEM_GIT_REF, "HEAD", CREDENTIALS_ID)) {
95 common.errorMsg("Failed to obtain system reclass with url: ${SYSTEM_GIT_URL} and ${SYSTEM_GIT_REF}")
96 }
chnyda6f78a9d2017-12-19 11:34:26 +010097 }
azvyagintsev7c4a3cf2018-07-08 08:43:33 +030098 }
chnyda7dd8cd92017-12-18 10:19:25 +010099
azvyagintsev7c4a3cf2018-07-08 08:43:33 +0300100 def testResult = false
101 def DockerCName = "${env.JOB_NAME.toLowerCase()}_${env.BUILD_TAG.toLowerCase()}"
102 testResult = saltModelTesting.setupAndTestNode(
103 "cfg01.${clusterDomain}",
104 clusterName,
105 EXTRA_FORMULAS,
106 testEnv,
107 'pkg',
108 DISTRIB_REVISION,
Vasyl Saienko772e1232018-07-23 14:42:24 +0300109 reclassVersion,
azvyagintsev7c4a3cf2018-07-08 08:43:33 +0300110 0,
111 false,
112 false,
113 '',
114 '',
115 DockerCName)
116 if (testResult) {
117 common.infoMsg("testModel finished: SUCCESS")
118 } else {
119 error('testModel finished: FAILURE')
azvyagintsev3ed704f2018-07-09 15:49:27 +0300120 throw new RuntimeException('Test stage finished: FAILURE')
azvyagintsev7c4a3cf2018-07-08 08:43:33 +0300121 }
chnyda7dd8cd92017-12-18 10:19:25 +0100122
chnydabc63c9a2017-05-30 15:37:54 +0200123}
124
125def gerritRef
126try {
127 gerritRef = GERRIT_REFSPEC
128} catch (MissingPropertyException e) {
129 gerritRef = null
chnydae80bb922017-05-29 17:48:40 +0200130}
Jakub Josefa63f9862018-01-11 17:58:38 +0100131timeout(time: 12, unit: 'HOURS') {
132 node("python&&docker") {
133 def templateEnv = "${env.WORKSPACE}"
134 def cutterEnv = "${env.WORKSPACE}/cutter"
135 def jinjaEnv = "${env.WORKSPACE}/jinja"
chnydae80bb922017-05-29 17:48:40 +0200136
Jakub Josefa63f9862018-01-11 17:58:38 +0100137 try {
138 stage("Cleanup") {
139 sh("rm -rf * || true")
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400140 }
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400141
Jakub Josefa63f9862018-01-11 17:58:38 +0100142 stage ('Download Cookiecutter template') {
143 if (gerritRef) {
144 def gerritChange = gerrit.getGerritChange(GERRIT_NAME, GERRIT_HOST, GERRIT_CHANGE_NUMBER, CREDENTIALS_ID)
145 merged = gerritChange.status == "MERGED"
146 if(!merged){
147 checkouted = gerrit.gerritPatchsetCheckout ([
148 credentialsId : CREDENTIALS_ID
149 ])
150 } else{
151 common.successMsg("Change ${GERRIT_CHANGE_NUMBER} is already merged, no need to gate them")
152 }
153 } else {
154 git.checkoutGitRepository(templateEnv, COOKIECUTTER_TEMPLATE_URL, COOKIECUTTER_TEMPLATE_BRANCH, CREDENTIALS_ID)
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400155 }
156 }
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400157
Jakub Josefa63f9862018-01-11 17:58:38 +0100158 stage("Setup") {
159 python.setupCookiecutterVirtualenv(cutterEnv)
160 }
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400161
Jakub Josefa63f9862018-01-11 17:58:38 +0100162 stage("Check workflow_definition") {
163 sh "python ${env.WORKSPACE}/workflow_definition_test.py"
164 }
165
166 def contextFiles
167 dir("${templateEnv}/contexts") {
168 contextFiles = findFiles(glob: "*.yml")
169 }
170
171 def contextFileList = []
172 for (int i = 0; i < contextFiles.size(); i++) {
173 contextFileList << contextFiles[i]
174 }
175
176 stage("generate-model") {
177 for (contextFile in contextFileList) {
178 generateModel(contextFile, cutterEnv)
179 }
180 }
181
182 dir("${env.WORKSPACE}") {
183 sh(returnStatus: true, script: "tar -zcvf model.tar.gz -C model .")
184 archiveArtifacts artifacts: "model.tar.gz"
185 }
186
187 stage("test-nodes") {
188 def partitions = common.partitionList(contextFileList, PARALLEL_NODE_GROUP_SIZE.toInteger())
189 def buildSteps = [:]
Richard Felkl9351d032018-06-28 15:03:14 +0200190 partitions.eachWithIndex { partition, i ->
Jakub Josefa63f9862018-01-11 17:58:38 +0100191 buildSteps.put("partition-${i}", new HashMap<String,org.jenkinsci.plugins.workflow.cps.CpsClosure2>())
Richard Felkl9351d032018-06-28 15:03:14 +0200192 for(part in partition){
193 def basename = sh(script: "basename ${part} .yml", returnStdout: true).trim()
Jakub Josefa63f9862018-01-11 17:58:38 +0100194 def testEnv = "${env.WORKSPACE}/model/${basename}"
195 buildSteps.get("partition-${i}").put(basename, { testModel(basename, testEnv) })
196 }
197 }
198 common.serial(buildSteps)
199 }
200
201 stage ('Clean workspace directories') {
202 sh(returnStatus: true, script: "rm -rfv * > /dev/null || true")
203 }
204
205 } catch (Throwable e) {
206 currentBuild.result = "FAILURE"
207 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
208 throw e
209 } finally {
210 def dummy = "dummy"
211 //FAILING common.sendNotification(currentBuild.result,"",["slack"])
212 }
chnydae80bb922017-05-29 17:48:40 +0200213 }
214}