blob: fedbd14a244426847d69c059de5589dee0354b9f [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
chnyda467f10f2017-05-30 17:25:07 +02007def generateSaltMaster(modEnv, clusterDomain, clusterName) {
8 def nodeFile = "${modEnv}/nodes/cfg01.${clusterDomain}.yml"
chnydae80bb922017-05-29 17:48:40 +02009 def nodeString = """classes:
10- cluster.${clusterName}.infra.config
11parameters:
12 _param:
13 linux_system_codename: xenial
14 reclass_data_revision: master
15 linux:
16 system:
17 name: cfg01
18 domain: ${clusterDomain}
19"""
chnyda467f10f2017-05-30 17:25:07 +020020 sh "mkdir -p ${modEnv}/nodes/"
21 println "Create file ${nodeFile}"
chnydae80bb922017-05-29 17:48:40 +020022 writeFile(file: nodeFile, text: nodeString)
23}
24
chnyda467f10f2017-05-30 17:25:07 +020025def generateModel(modelFile, cutterEnv) {
chnydabc63c9a2017-05-30 15:37:54 +020026 def templateEnv = "${env.WORKSPACE}"
27 def modelEnv = "${env.WORKSPACE}/model"
chnyda467f10f2017-05-30 17:25:07 +020028 def basename = sh(script: "basename ${modelFile} .yml", returnStdout: true).trim()
chnydabc63c9a2017-05-30 15:37:54 +020029 def generatedModel = "${modelEnv}/${basename}"
30 def testEnv = "${env.WORKSPACE}/test"
chnyda467f10f2017-05-30 17:25:07 +020031 def content = readFile(file: "${templateEnv}/contexts/${modelFile}")
chnydabc63c9a2017-05-30 15:37:54 +020032 def templateContext = readYaml text: content
chnydae80bb922017-05-29 17:48:40 +020033 def clusterDomain = templateContext.default_context.cluster_domain
34 def clusterName = templateContext.default_context.cluster_name
chnydabc63c9a2017-05-30 15:37:54 +020035 def outputDestination = "${generatedModel}/classes/cluster/${clusterName}"
chnydae80bb922017-05-29 17:48:40 +020036 def targetBranch = "feature/${clusterName}"
chnydabc63c9a2017-05-30 15:37:54 +020037 def templateBaseDir = "${env.WORKSPACE}"
38 def templateDir = "${templateEnv}/dir"
chnydae80bb922017-05-29 17:48:40 +020039 def templateOutputDir = templateBaseDir
chnydabc63c9a2017-05-30 15:37:54 +020040 sh "rm -rf ${generatedModel} || true"
chnydae80bb922017-05-29 17:48:40 +020041
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020042 common.infoMsg("Generating model from context ${modelFile}")
chnydae79b94e2017-07-10 09:46:25 +020043
Mikhail Ivanov30c91f42017-11-07 20:42:26 +040044 def productList = ["infra", "cicd", "opencontrail", "kubernetes", "openstack", "oss", "stacklight", "ceph"]
chnyda467f10f2017-05-30 17:25:07 +020045 for (product in productList) {
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020046
47 // get templateOutputDir and productDir
48 if (product.startsWith("stacklight")) {
49 templateOutputDir = "${env.WORKSPACE}/output/stacklight"
50 try {
51 productDir = "stacklight" + templateContext.default_context['stacklight_version']
52 } catch (Throwable e) {
53 productDir = "stacklight1"
54 }
55 } else {
56 templateOutputDir = "${env.WORKSPACE}/output/${product}"
57 productDir = product
58 }
59
chnyda467f10f2017-05-30 17:25:07 +020060 if (product == "infra" || (templateContext.default_context["${product}_enabled"]
61 && templateContext.default_context["${product}_enabled"].toBoolean())) {
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020062
63 templateDir = "${templateEnv}/cluster_product/${productDir}"
64 common.infoMsg("Generating product " + product + " from " + templateDir + " to " + templateOutputDir)
65
chnyda467f10f2017-05-30 17:25:07 +020066 sh "rm -rf ${templateOutputDir} || true"
67 sh "mkdir -p ${templateOutputDir}"
68 sh "mkdir -p ${outputDestination}"
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020069
chnyda467f10f2017-05-30 17:25:07 +020070 python.buildCookiecutterTemplate(templateDir, content, templateOutputDir, cutterEnv, templateBaseDir)
71 sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
Tomáš Kukrál9a6821e2017-07-24 11:07:01 +020072 } else {
73 common.warningMsg("Product " + product + " is disabled")
chnydae80bb922017-05-29 17:48:40 +020074 }
75 }
chnyda467f10f2017-05-30 17:25:07 +020076 generateSaltMaster(generatedModel, clusterDomain, clusterName)
chnydae80bb922017-05-29 17:48:40 +020077}
78
chnyda467f10f2017-05-30 17:25:07 +020079def testModel(modelFile, testEnv) {
chnydabc63c9a2017-05-30 15:37:54 +020080 def templateEnv = "${env.WORKSPACE}"
chnyda467f10f2017-05-30 17:25:07 +020081 def content = readFile(file: "${templateEnv}/contexts/${modelFile}.yml")
chnydabc63c9a2017-05-30 15:37:54 +020082 def templateContext = readYaml text: content
Jakub Josef1308e282017-08-18 14:08:54 +020083 def clusterName = templateContext.default_context.cluster_name
chnydabc63c9a2017-05-30 15:37:54 +020084 def clusterDomain = templateContext.default_context.cluster_domain
chnyda6f78a9d2017-12-19 11:34:26 +010085 if (SYSTEM_GIT_URL == "") {
86 git.checkoutGitRepository("${testEnv}/classes/system", RECLASS_MODEL_URL, RECLASS_MODEL_BRANCH, CREDENTIALS_ID)
87 } else {
88 dir("${testEnv}/classes/system") {
89 if (!gerrit.gerritPatchsetCheckout(SYSTEM_GIT_URL, SYSTEM_GIT_REF, "HEAD", CREDENTIALS_ID)) {
90 common.errorMsg("Failed to obtain system reclass with url: ${SYSTEM_GIT_URL} and ${SYSTEM_GIT_REF}")
91 }
92 }
93 }
chnyda7dd8cd92017-12-18 10:19:25 +010094
95 def nbTry = 0
96 while (nbTry < 5) {
97 nbTry++
98 try {
Kirill Mashchenko18071f62018-06-29 12:42:16 +030099 def DockerCName = "${env.JOB_NAME.toLowerCase()}_${env.BUILD_TAG.toLowerCase()}"
Kirill Mashchenkoa71cc702018-06-29 15:58:11 +0300100 saltModelTesting.setupAndTestNode(
101 "cfg01.${clusterDomain}",
102 clusterName,
103 EXTRA_FORMULAS,
104 testEnv,
105 'pkg',
106 DISTRIB_REVISION,
107 'master',
108 0,
109 false,
110 false,
111 '',
112 '',
113 DockerCName)
chnyda7dd8cd92017-12-18 10:19:25 +0100114 break
115 } catch (Exception e) {
116 if (e.getMessage() == "script returned exit code 124") {
117 common.errorMsg("Impossible to test node due to timeout of salt-master, retriggering")
118 } else {
119 throw e
120 }
121 }
122 }
123
chnydabc63c9a2017-05-30 15:37:54 +0200124}
125
126def gerritRef
127try {
128 gerritRef = GERRIT_REFSPEC
129} catch (MissingPropertyException e) {
130 gerritRef = null
chnydae80bb922017-05-29 17:48:40 +0200131}
Jakub Josefa63f9862018-01-11 17:58:38 +0100132timeout(time: 12, unit: 'HOURS') {
133 node("python&&docker") {
134 def templateEnv = "${env.WORKSPACE}"
135 def cutterEnv = "${env.WORKSPACE}/cutter"
136 def jinjaEnv = "${env.WORKSPACE}/jinja"
chnydae80bb922017-05-29 17:48:40 +0200137
Jakub Josefa63f9862018-01-11 17:58:38 +0100138 try {
139 stage("Cleanup") {
140 sh("rm -rf * || true")
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400141 }
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400142
Jakub Josefa63f9862018-01-11 17:58:38 +0100143 stage ('Download Cookiecutter template') {
144 if (gerritRef) {
145 def gerritChange = gerrit.getGerritChange(GERRIT_NAME, GERRIT_HOST, GERRIT_CHANGE_NUMBER, CREDENTIALS_ID)
146 merged = gerritChange.status == "MERGED"
147 if(!merged){
148 checkouted = gerrit.gerritPatchsetCheckout ([
149 credentialsId : CREDENTIALS_ID
150 ])
151 } else{
152 common.successMsg("Change ${GERRIT_CHANGE_NUMBER} is already merged, no need to gate them")
153 }
154 } else {
155 git.checkoutGitRepository(templateEnv, COOKIECUTTER_TEMPLATE_URL, COOKIECUTTER_TEMPLATE_BRANCH, CREDENTIALS_ID)
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400156 }
157 }
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400158
Jakub Josefa63f9862018-01-11 17:58:38 +0100159 stage("Setup") {
160 python.setupCookiecutterVirtualenv(cutterEnv)
161 }
Ruslan Kamaldinov6feef402017-08-02 16:55:58 +0400162
Jakub Josefa63f9862018-01-11 17:58:38 +0100163 stage("Check workflow_definition") {
164 sh "python ${env.WORKSPACE}/workflow_definition_test.py"
165 }
166
167 def contextFiles
168 dir("${templateEnv}/contexts") {
169 contextFiles = findFiles(glob: "*.yml")
170 }
171
172 def contextFileList = []
173 for (int i = 0; i < contextFiles.size(); i++) {
174 contextFileList << contextFiles[i]
175 }
176
177 stage("generate-model") {
178 for (contextFile in contextFileList) {
179 generateModel(contextFile, cutterEnv)
180 }
181 }
182
183 dir("${env.WORKSPACE}") {
184 sh(returnStatus: true, script: "tar -zcvf model.tar.gz -C model .")
185 archiveArtifacts artifacts: "model.tar.gz"
186 }
187
188 stage("test-nodes") {
189 def partitions = common.partitionList(contextFileList, PARALLEL_NODE_GROUP_SIZE.toInteger())
190 def buildSteps = [:]
Richard Felkl9351d032018-06-28 15:03:14 +0200191 partitions.eachWithIndex { partition, i ->
Jakub Josefa63f9862018-01-11 17:58:38 +0100192 buildSteps.put("partition-${i}", new HashMap<String,org.jenkinsci.plugins.workflow.cps.CpsClosure2>())
Richard Felkl9351d032018-06-28 15:03:14 +0200193 for(part in partition){
194 def basename = sh(script: "basename ${part} .yml", returnStdout: true).trim()
Jakub Josefa63f9862018-01-11 17:58:38 +0100195 def testEnv = "${env.WORKSPACE}/model/${basename}"
196 buildSteps.get("partition-${i}").put(basename, { testModel(basename, testEnv) })
197 }
198 }
199 common.serial(buildSteps)
200 }
201
202 stage ('Clean workspace directories') {
203 sh(returnStatus: true, script: "rm -rfv * > /dev/null || true")
204 }
205
206 } catch (Throwable e) {
207 currentBuild.result = "FAILURE"
208 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
209 throw e
210 } finally {
211 def dummy = "dummy"
212 //FAILING common.sendNotification(currentBuild.result,"",["slack"])
213 }
chnydae80bb922017-05-29 17:48:40 +0200214 }
215}