| package com.mirantis.mcp |
| |
| import com.cloudbees.groovy.cps.NonCPS |
| @Grab(group='org.yaml', module='snakeyaml', version='1.17') |
| import org.yaml.snakeyaml.Yaml |
| |
| /** |
| * https://issues.jenkins-ci.org/browse/JENKINS-26481 |
| * fix groovy List.collect() |
| **/ |
| @NonCPS |
| def constructString(ArrayList options, String keyOption, String separator = " ") { |
| return options.collect { keyOption + it }.join(separator).replaceAll("\n", "") |
| } |
| |
| /** |
| * Generate current timestamp |
| * |
| * @param format Defaults to yyyyMMddHHmmss |
| */ |
| def getDatetime(format = "yyyyMMddHHmmss") { |
| def now = new Date(); |
| return now.format(format, TimeZone.getTimeZone('UTC')); |
| } |
| |
| /** |
| * Run tox with or without specified environment |
| * @param env String, name of environment |
| */ |
| def runTox(String env = null) { |
| if (env) { |
| sh "tox -v -e ${env}" |
| } else { |
| sh "tox -v" |
| } |
| } |
| |
| /** |
| * Convert YAML document to Map object |
| * @param data YAML string |
| */ |
| @NonCPS |
| def loadYAML(String data) { |
| def yaml = new Yaml() |
| return yaml.load(data) |
| } |
| |
| /** |
| * Convert Map object to YAML string |
| * @param map Map object |
| */ |
| @NonCPS |
| def dumpYAML(Map map) { |
| def yaml = new Yaml() |
| return yaml.dump(map) |
| } |
| |
| /** |
| * Render jinja template |
| * @param templateVars String, A dict, a dict subclass, json or some keyword arguments |
| * @param templateFile String, jinja template file path |
| * @param resultFile String, result/generate file path |
| * |
| * Usage example: |
| * |
| * def common = new com.mirantis.mcp.Common() |
| * common.renderJinjaTemplate( |
| * "${NODE_JSON}", |
| * "${WORKSPACE}/inventory/inventory.cfg", |
| * "${WORKSPACE}/inventory/inventory.cfg") |
| * where NODE_JSON= data in json format |
| */ |
| def renderJinjaTemplate(String templateVars, String templateFile, String resultFile) { |
| |
| sh """ |
| python -c " |
| import sys |
| import jinja2 |
| from jinja2 import Template |
| |
| # Useful for very coarse version differentiation. |
| PY2 = sys.version_info[0] == 2 |
| PY3 = sys.version_info[0] == 3 |
| PY34 = sys.version_info[0:2] >= (3, 4) |
| |
| if PY3: |
| string_types = str, |
| else: |
| string_types = basestring |
| |
| |
| def to_bool(a): |
| ''' return a bool for the arg ''' |
| if a is None or type(a) == bool: |
| return a |
| if isinstance(a, string_types): |
| a = a.lower() |
| if a in ['yes', 'on', '1', 'true', 1]: |
| return True |
| else: |
| return False |
| |
| |
| def generate(templateVars, templateFile, resultFile): |
| templateLoader = jinja2.FileSystemLoader(searchpath='/') |
| templateEnv = jinja2.Environment(loader=templateLoader) |
| templateEnv.filters['bool'] = to_bool |
| template = templateEnv.get_template(templateFile) |
| outputText = template.render(templateVars) |
| Template(outputText).stream().dump(resultFile) |
| |
| generate(${templateVars}, '${templateFile}', '${resultFile}') |
| " |
| cat ${resultFile} |
| """ |
| } |
| |
| /** |
| * Run function on k8s cluster |
| * |
| * @param config LinkedHashMap |
| * config includes next parameters: |
| * - label, pod label |
| * - function, code that should be run on k8s cluster |
| * - jnlpImg, jnlp slave image |
| * - slaveImg, slave image |
| * |
| * Usage example: |
| * |
| * def runFunc = new com.mirantis.mcp.Common() |
| * runFunc.runOnKubernetes ([ |
| * function : this.&buildCalicoContainers, |
| * jnlpImg: 'docker-prod-virtual.docker.mirantis.net/mirantis/jenkins-slave-images/jnlp-slave:latest', |
| * slaveImg : 'sandbox-docker-dev-local.docker.mirantis.net/skulanov/jenkins-slave-images/calico-slave:1' |
| * ]) |
| * // promotion example. In case of promotion we need only jnlp container |
| * def runFunc = new com.mirantis.mcp.Common() |
| * runFunc.runOnKubernetes ([ |
| * jnlpImg: 'docker-prod-virtual.docker.mirantis.net/mirantis/jenkins-slave-images/jnlp-slave:latest', |
| * function : this.&promote_artifacts |
| * ]) |
| */ |
| def runOnKubernetes(LinkedHashMap config) { |
| |
| |
| def jenkinsSlaveImg = config.get('slaveImg', 'none') |
| def jnlpSlaveImg = config.get('jnlpImg', 'none') |
| def lbl = config.get('label', "buildpod.${env.JOB_NAME}.${env.BUILD_NUMBER}".replace('-', '_').replace('/', '_')) |
| def toRun = config.get('function', 'none') |
| |
| if (jnlpSlaveImg == 'none') { |
| error('jnlp Slave image MUST be defined') |
| } |
| |
| if (toRun == 'none'){ |
| error('Code that should be run on k8s MUST be passed along with function parameter') |
| } |
| |
| if (jenkinsSlaveImg == 'none'){ |
| // we are running jnlp container only, since no jenkinsSlaveImg is specified, so |
| // we are in promotion mode |
| podTemplate(label: lbl, |
| containers: [ |
| containerTemplate( |
| name: 'jnlp', |
| image: jnlpSlaveImg, |
| args: '${computer.jnlpmac} ${computer.name}' |
| ) |
| ], |
| ) { |
| node(lbl){ |
| container('jnlp') { |
| toRun() |
| } |
| } |
| } |
| |
| } else { |
| podTemplate(label: lbl, |
| containers: [ |
| containerTemplate( |
| name: 'jnlp', |
| image: jnlpSlaveImg, |
| args: '${computer.jnlpmac} ${computer.name}' |
| ), |
| containerTemplate( |
| name: 'k8s-slave', |
| image: jenkinsSlaveImg, |
| alwaysPullImage: false, |
| ttyEnabled: true, |
| privileged: true |
| ) |
| ], |
| ) { |
| node(lbl){ |
| container('k8s-slave') { |
| return toRun() |
| } |
| } |
| } |
| } //else |
| |
| } |