Merge "Changed default gerrit checkout branch, fixed gating"
diff --git a/cicd-lab-pipeline.groovy b/cicd-lab-pipeline.groovy
index 972ab81..adaedd0 100644
--- a/cicd-lab-pipeline.groovy
+++ b/cicd-lab-pipeline.groovy
@@ -142,31 +142,31 @@
stage("Deploy Docker services") {
salt.enforceState(saltMaster, 'I@docker:swarm:role:master', 'docker.client')
-
- // XXX: Hack to fix dependency of gerrit on mysql
- print common.prettyPrint(salt.cmdRun(saltMaster, 'I@docker:swarm:role:master', "docker service rm gerrit; sleep 5; rm -rf /srv/volumes/gerrit/*"))
-
- timeout(10) {
- salt.cmdRun(saltMaster, 'I@docker:swarm:role:master', 'apt-get install -y mysql-client')
- println "Waiting for MySQL to come up.."
- salt.cmdRun(saltMaster, 'I@docker:swarm:role:master', 'while true; do mysql -h172.16.10.254 -ppassword -e"show status;" >/dev/null && break; done')
- }
- salt.enforceState(saltMaster, 'I@docker:swarm:role:master', 'docker.client')
- // ---- cut here (end of hack) ----
}
stage("Configure CI/CD services") {
salt.syncAll(saltMaster, '*')
// Aptly
+ timeout(10) {
+ println "Waiting for Aptly to come up.."
+ salt.cmdRun(saltMaster, 'I@aptly:server', 'while true; do curl -svf http://172.16.10.254:8084/api/version >/dev/null && break; done')
+ }
salt.enforceState(saltMaster, 'I@aptly:server', 'aptly', true)
+ // OpenLDAP
+ timeout(10) {
+ println "Waiting for OpenLDAP to come up.."
+ salt.cmdRun(saltMaster, 'I@openldap:client', 'while true; do curl -svf ldap://172.16.10.254 >/dev/null && break; done')
+ }
+ salt.enforceState(saltMaster, 'I@openldap:client', 'openldap', true)
+
// Gerrit
timeout(10) {
println "Waiting for Gerrit to come up.."
salt.cmdRun(saltMaster, 'I@gerrit:client', 'while true; do curl -svf 172.16.10.254:8080 >/dev/null && break; done')
}
- retry(2) {
+ retry(3) {
// Needs to run twice to pass __virtual__ method of gerrit module
// after installation of dependencies
try {
@@ -262,6 +262,7 @@
9600 haproxy stats
8080 gerrit
8081 jenkins
+ 8089 LDAP administration
8091 Docker swarm visualizer
8090 Reclass-generated documentation
diff --git a/generate-cookiecutter-products.groovy b/generate-cookiecutter-products.groovy
new file mode 100644
index 0000000..2fd65bc
--- /dev/null
+++ b/generate-cookiecutter-products.groovy
@@ -0,0 +1,146 @@
+/**
+ * Generate cookiecutter cluster by individual products
+ *
+ * Expected parameters:
+ * COOKIECUTTER_TEMPLATE_CREDENTIALS Credentials to the Cookiecutter template repo.
+ * COOKIECUTTER_TEMPLATE_URL Cookiecutter template repo address.
+ * COOKIECUTTER_TEMPLATE_BRANCH Branch for the template.
+ * COOKIECUTTER_TEMPLATE_CONTEXT Context parameters for the template generation.
+ * COOKIECUTTER_INSTALL_CICD Whether to install CI/CD stack.
+ * COOKIECUTTER_INSTALL_CONTRAIL Whether to install OpenContrail SDN.
+ * COOKIECUTTER_INSTALL_KUBERNETES Whether to install Kubernetes.
+ * COOKIECUTTER_INSTALL_OPENSTACK Whether to install OpenStack cloud.
+ * COOKIECUTTER_INSTALL_STACKLIGHT Whether to install StackLight monitoring.
+ * RECLASS_MODEL_URL Reclass model repo address
+ * RECLASS_MODEL_CREDENTIALS Credentials to the Reclass model repo.
+ * RECLASS_MODEL_BRANCH Branch for the template to push to model.
+ *
+**/
+
+common = new com.mirantis.mk.Common()
+git = new com.mirantis.mk.Git()
+python = new com.mirantis.mk.Python()
+
+timestamps {
+ node() {
+ def templateEnv = "${env.WORKSPACE}/template"
+ def modelEnv = "${env.WORKSPACE}/model"
+
+ try {
+ def templateContext = python.loadJson(COOKIECUTTER_TEMPLATE_CONTEXT)
+ def templateDir = "${templateEnv}/template/dir"
+ def templateOutputDir = "${env.WORKSPACE}/template"
+ def cutterEnv = "${env.WORKSPACE}/cutter"
+ def jinjaEnv = "${env.WORKSPACE}/jinja"
+ def clusterName = templateContext.cluster_name
+ def clusterDomain = templateContext.cluster_domain
+ def targetBranch = "feature/${clusterName}"
+
+ stage ('Download Cookiecutter template') {
+ git.checkoutGitRepository(templateEnv, COOKIECUTTER_TEMPLATE_URL, COOKIECUTTER_TEMPLATE_BRANCH, COOKIECUTTER_TEMPLATE_CREDENTIALS)
+ }
+
+ stage ('Download full Reclass model') {
+ git.checkoutGitRepository(modelEnv, RECLASS_MODEL_URL, RECLASS_MODEL_BRANCH, RECLASS_MODEL_CREDENTIALS)
+ }
+
+ stage('Generate base infrastructure') {
+ templateDir = "${templateEnv}/cluster_product/infra"
+ templateOutputDir = "${env.WORKSPACE}/template/output_infra"
+ sh "mkdir -p ${templateOutputDir}"
+ python.setupCookiecutterVirtualenv(cutterEnv)
+ python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+ }
+
+ stage('Generate product CI/CD') {
+ if (COOKIECUTTER_INSTALL_CICD.toBoolean()) {
+ templateDir = "${templateEnv}/cluster_product/cicd"
+ templateOutputDir = "${env.WORKSPACE}/template/output_cicd"
+ sh "mkdir -p ${templateOutputDir}"
+ python.setupCookiecutterVirtualenv(cutterEnv)
+ python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+ }
+ }
+
+ stage('Generate product OpenContrail') {
+ if (COOKIECUTTER_INSTALL_CONTRAIL.toBoolean()) {
+ templateDir = "${templateEnv}/cluster_product/contrail"
+ templateOutputDir = "${env.WORKSPACE}/template/output_contrail"
+ sh "mkdir -p ${templateOutputDir}"
+ python.setupCookiecutterVirtualenv(cutterEnv)
+ python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+ }
+ }
+
+ stage('Generate product Kubernetes') {
+ if (COOKIECUTTER_INSTALL_KUBERNETES.toBoolean()) {
+ templateDir = "${templateEnv}/cluster_product/kubernetes"
+ templateOutputDir = "${env.WORKSPACE}/template/output_kubernetes"
+ sh "mkdir -p ${templateOutputDir}"
+ python.setupCookiecutterVirtualenv(cutterEnv)
+ python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+ }
+ }
+
+ stage('Generate product OpenStack') {
+ if (COOKIECUTTER_INSTALL_OPENSTACK.toBoolean()) {
+ templateDir = "${templateEnv}/cluster_product/openstack"
+ templateOutputDir = "${env.WORKSPACE}/template/output_openstack"
+ sh "mkdir -p ${templateOutputDir}"
+ python.setupCookiecutterVirtualenv(cutterEnv)
+ python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+ }
+ }
+
+ stage('Generate product StackLight') {
+ if (COOKIECUTTER_INSTALL_STACKLIGHT.toBoolean()) {
+ templateDir = "${templateEnv}/cluster_product/stacklight"
+ templateOutputDir = "${env.WORKSPACE}/template/output_stacklight"
+ sh "mkdir -p ${templateOutputDir}"
+ python.setupCookiecutterVirtualenv(cutterEnv)
+ python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+ }
+ }
+
+ stage('Generate new SaltMaster node') {
+ def nodeFile = "${modelEnv}/nodes/cfg01.${clusterDomain}.yml"
+ def nodeString = """classes:
+- cluster.${clusterName}.infra.config
+parameters:
+ _param:
+ linux_system_codename: xenial
+ reclass_data_revision: master
+ linux:
+ system:
+ name: cfg01
+ domain: ${clusterDomain}
+"""
+ writeFile(file: nodeFile, text: nodeString)
+ }
+
+ stage('Inject changes to Reclass model') {
+ git.changeGitBranch(modelEnv, targetBranch)
+ def outputSource = "${templateOutputDir}/${clusterName}"
+ def outputDestination = "${modelEnv}/classes/cluster/${clusterName}"
+ sh(returnStdout: true, script: "cp ${outputSource} ${outputDestination} -r")
+ git.commitGitChanges(modelEnv, "Added new cluster ${clusterName}")
+ archiveArtifacts artifacts: modelEnv
+ }
+
+ stage ('Push changes to Reclass model') {
+ git.pushGitChanges(modelEnv, targetBranch, 'origin', RECLASS_MODEL_CREDENTIALS)
+ }
+
+ } catch (Throwable e) {
+ // If there was an error or exception thrown, the build failed
+ currentBuild.result = "FAILURE"
+ throw e
+ } finally {
+ stage ('Clean workspace directories') {
+ sh(returnStdout: true, script: "rm ${templateEnv} -rf")
+ sh(returnStdout: true, script: "rm ${modelEnv} -rf")
+ }
+ // common.sendNotification(currentBuild.result,"",["slack"])
+ }
+ }
+}
diff --git a/lab-pipeline.groovy b/lab-pipeline.groovy
index a6efaca..5b7cc11 100644
--- a/lab-pipeline.groovy
+++ b/lab-pipeline.groovy
@@ -41,7 +41,7 @@
openstack = new com.mirantis.mk.Openstack()
salt = new com.mirantis.mk.Salt()
common = new com.mirantis.mk.Common()
-
+test = new com.mirantis.mk.Test()
timestamps {
node {
@@ -50,6 +50,7 @@
// Prepare machines
//
stage ('Create infrastructure') {
+
if (STACK_TYPE == 'heat') {
// value defaults
def openstackCloud
@@ -99,7 +100,7 @@
saltMasterHost = openstack.getHeatStackOutputParam(openstackCloud, HEAT_STACK_NAME, 'salt_master_ip', openstackEnv)
currentBuild.description = "${HEAT_STACK_NAME}: ${saltMasterHost}"
- if (INSTALL.toLowerCase().contains('kvm')) {
+ if (common.checkContains('INSTALL', 'kvm')) {
saltPort = 6969
} else {
saltPort = 6969
@@ -122,7 +123,7 @@
// Install
//
- if (INSTALL.toLowerCase().contains('core')) {
+ if (common.checkContains('INSTALL', 'core')) {
stage('Install core infrastructure') {
// salt.master, reclass
// refresh_pillar
@@ -131,17 +132,19 @@
//orchestrate.installFoundationInfra(saltMaster)
salt.enforceState(saltMaster, 'I@salt:master', ['salt.master', 'reclass'], true)
+ salt.enforceState(saltMaster, '*', ['linux.system'], true)
+ salt.enforceState(saltMaster, '*', ['salt.minion'], true)
salt.runSaltProcessStep(saltMaster, 'I@linux:system', 'saltutil.refresh_pillar', [], null, true)
salt.runSaltProcessStep(saltMaster, 'I@linux:system', 'saltutil.sync_all', [], null, true)
salt.enforceState(saltMaster, 'I@linux:system', ['linux', 'openssh', 'salt.minion', 'ntp'], true)
- if (INSTALL.toLowerCase().contains('kvm')) {
+ if (common.checkContains('INSTALL', 'kvm')) {
//orchestrate.installInfraKvm(saltMaster)
- salt.runSaltProcessStep(saltMaster, 'I@linux:system', 'saltutil.refresh_pillar', [], null, true)
- salt.runSaltProcessStep(saltMaster, 'I@linux:system', 'saltutil.sync_all', [], null, true)
+ //salt.runSaltProcessStep(saltMaster, 'I@linux:system', 'saltutil.refresh_pillar', [], null, true)
+ //salt.runSaltProcessStep(saltMaster, 'I@linux:system', 'saltutil.sync_all', [], null, true)
- salt.enforceState(saltMaster, 'I@salt:control', ['salt.minion', 'linux.system', 'linux.network', 'ntp'], true)
+ //salt.enforceState(saltMaster, 'I@salt:control', ['salt.minion', 'linux.system', 'linux.network', 'ntp'], true)
salt.enforceState(saltMaster, 'I@salt:control', 'libvirt', true)
salt.enforceState(saltMaster, 'I@salt:control', 'salt.control', true)
@@ -167,7 +170,7 @@
}
// install k8s
- if (INSTALL.toLowerCase().contains('k8s')) {
+ if (common.checkContains('INSTALL', 'k8s')) {
stage('Install Kubernetes infra') {
//orchestrate.installOpenstackMcpInfra(saltMaster)
@@ -235,7 +238,7 @@
}
// install openstack
- if (INSTALL.toLowerCase().contains('openstack')) {
+ if (common.checkContains('INSTALL', 'openstack')) {
// install Infra and control, tests, ...
stage('Install OpenStack infra') {
@@ -258,14 +261,19 @@
salt.runSaltProcessStep(saltMaster, 'I@glusterfs:server', 'cmd.run', ['gluster volume status'], null, true)
// Install rabbitmq
- salt.enforceState(saltMaster, 'I@rabbitmq:server', 'rabbitmq', true, false)
-
+ withEnv(['ASK_ON_ERROR=false']){
+ retry(2) {
+ salt.enforceState(saltMaster, 'I@rabbitmq:server', 'rabbitmq', true)
+ }
+ }
// Check the rabbitmq status
salt.runSaltProcessStep(saltMaster, 'I@rabbitmq:server', 'cmd.run', ['rabbitmqctl cluster_status'])
// Install galera
- retry(2) {
- salt.enforceState(saltMaster, 'I@galera:master', 'galera', true)
+ withEnv(['ASK_ON_ERROR=false']){
+ retry(2) {
+ salt.enforceState(saltMaster, 'I@galera:master', 'galera', true)
+ }
}
salt.enforceState(saltMaster, 'I@galera:slave', 'galera', true)
@@ -348,7 +356,7 @@
stage('Install OpenStack network') {
//orchestrate.installOpenstackMkNetwork(saltMaster, physical)
- if (INSTALL.toLowerCase().contains('contrail')) {
+ if (common.checkContains('INSTALL', 'contrail')) {
// Install opencontrail database services
//runSaltProcessStep(saltMaster, 'I@opencontrail:database', 'state.sls', ['opencontrail.database'], 1)
try {
@@ -371,7 +379,7 @@
// Test opencontrail
salt.runSaltProcessStep(saltMaster, 'I@opencontrail:control', 'cmd.run', ['contrail-status'], null, true)
- } else if (INSTALL.toLowerCase().contains('ovs')) {
+ } else if (common.checkContains('INSTALL', 'ovs')) {
// Apply gateway
salt.runSaltProcessStep(saltMaster, 'I@neutron:gateway', 'state.apply', [], null, true)
}
@@ -388,7 +396,7 @@
salt.runSaltProcessStep(saltMaster, 'I@nova:compute', 'state.apply', [], null, true)
}
- if (INSTALL.toLowerCase().contains('contrail')) {
+ if (common.checkContains('INSTALL', 'contrail')) {
// Provision opencontrail control services
salt.enforceState(saltMaster, 'I@opencontrail:database:id:1', 'opencontrail.client', true)
// Provision opencontrail virtual routers
@@ -402,7 +410,7 @@
}
- if (INSTALL.toLowerCase().contains('stacklight')) {
+ if (common.checkContains('INSTALL', 'stacklight')) {
stage('Install StackLight') {
// infra install
// Install the StackLight backends
@@ -506,7 +514,7 @@
// Test
//
- if (TEST.toLowerCase().contains('k8s')) {
+ if (common.checkContains('TEST', 'k8s')) {
stage('Run k8s bootstrap tests') {
orchestrate.runConformanceTests(saltMaster, K8S_API_SERVER, 'tomkukral/k8s-scripts')
}
@@ -516,7 +524,7 @@
}
}
- if (TEST.toLowerCase().contains('openstack')) {
+ if (common.checkContains('TEST', 'openstack')) {
stage('Run OpenStack tests') {
test.runTempestTests(saltMaster, TEMPEST_IMAGE_LINK)
}
@@ -538,14 +546,15 @@
throw e
} finally {
- // send notification
- common.sendNotification(currentBuild.result,HEAT_STACK_NAME,["slack"])
//
// Clean
//
if (STACK_TYPE == 'heat') {
+ // send notification
+ common.sendNotification(currentBuild.result, HEAT_STACK_NAME, ["slack"])
+
if (HEAT_STACK_DELETE.toBoolean() == true) {
common.errorMsg('Heat job cleanup triggered')
stage('Trigger cleanup job') {
diff --git a/mk-k8s-simple-deploy-pipeline.groovy b/mk-k8s-simple-deploy-pipeline.groovy
index c82771f..02f7709 100644
--- a/mk-k8s-simple-deploy-pipeline.groovy
+++ b/mk-k8s-simple-deploy-pipeline.groovy
@@ -86,7 +86,7 @@
}
if (RUN_TESTS == "1") {
- sleep(30000)
+ sleep(30)
stage('Run k8s bootstrap tests') {
test.runConformanceTests(saltMaster, K8S_API_SERVER, 'tomkukral/k8s-scripts')
}
diff --git a/test-nodejs-pipeline.groovy b/test-nodejs-pipeline.groovy
new file mode 100644
index 0000000..35d8317
--- /dev/null
+++ b/test-nodejs-pipeline.groovy
@@ -0,0 +1,52 @@
+/**
+* JS testing pipeline
+* CREDENTIALS_ID - gerrit credentials id
+* NODE_IMAGE - NodeJS with NPM Docker image name
+* COMMANDS - a list of command(s) to run
+**/
+
+gerrit = new com.mirantis.mk.Gerrit()
+common = new com.mirantis.mk.Common()
+
+node("docker") {
+ def containerID
+ try {
+ stage ('Checkout source code') {
+ gerrit.gerritPatchsetCheckout ([
+ credentialsId : CREDENTIALS_ID,
+ withWipeOut : true,
+ ])
+ }
+ stage ('Start container') {
+ def workspace = common.getWorkspace()
+ containerID = sh(
+ script: "docker run -d -v ${workspace}:/opt/workspace:rw ${NODE_IMAGE}",
+ returnStdout: true,
+ ).trim()
+ }
+ stage ('Execute commands') {
+ assert containerID != null
+ def cmds = COMMANDS.tokenize('\n')
+ for (int i = 0; i < cmds.size(); i++) {
+ def cmd = cmds[i]
+ def output = sh(
+ script: "docker exec ${containerID} ${cmd}",
+ returnStdout: true,
+ ).trim()
+ common.infoMsg(output)
+ }
+ }
+ } catch (Throwable e) {
+ currentBuild.result = 'FAILURE'
+ common.errorMsg("Build failed due to some commands failed.")
+ throw e
+ } finally {
+ common.sendNotification(currentBuild.result, "" ,["slack"])
+ stage ('Remove container') {
+ if (containerID != null) {
+ sh "docker stop -t 0 ${containerID}"
+ sh "docker rm ${containerID}"
+ }
+ }
+ }
+}
diff --git a/update-package.groovy b/update-package.groovy
index 6c31c95..b37fe22 100644
--- a/update-package.groovy
+++ b/update-package.groovy
@@ -24,6 +24,7 @@
def result
def packages
def command
+def commandKwargs
node() {
try {
@@ -70,15 +71,17 @@
}
if (TARGET_PACKAGES != "") {
- command = "pkg.install";
+ command = "pkg.install"
packages = TARGET_PACKAGES.tokenize(' ')
+ commandKwargs = ['only_upgrade': 'true']
}else {
command = "pkg.upgrade"
packages = null
}
stage('Apply package upgrades on sample') {
- salt.runSaltProcessStep(saltMaster, targetLiveSubset, command, packages, null, true)
+ out = salt.runSaltCommand(saltMaster, 'local', ['expression': targetLiveSubset, 'type': 'compound'], command, null, packages, commandKwargs)
+ salt.printSaltCommandResult(out)
}
stage('Confirm package upgrades on all nodes') {
@@ -88,7 +91,8 @@
}
stage('Apply package upgrades on all nodes') {
- salt.runSaltProcessStep(saltMaster, targetLiveAll, command, packages, null, true)
+ out = salt.runSaltCommand(saltMaster, 'local', ['expression': targetLiveAll, 'type': 'compound'], command, null, packages, commandKwargs)
+ salt.printSaltCommandResult(out)
}
} catch (Throwable e) {