blob: 6e5705e02b28d3bfcf27bd5a34971f5e2a9c4d05 [file] [log] [blame]
/**
* Helper pipeline for AWS deployments from kqueen
*
* Expected parameters:
* STACK_NAME Infrastructure stack name
* STACK_TEMPLATE File with stack template
*
* STACK_TEMPLATE_URL URL to git repo with stack templates
* STACK_TEMPLATE_CREDENTIALS Credentials to the templates repo
* STACK_TEMPLATE_BRANCH Stack templates repo branch
* STACK_COMPUTE_COUNT Number of compute nodes to launch
*
* HEAT_STACK_ENVIRONMENT Heat stack environmental parameters
* HEAT_STACK_ZONE Heat stack availability zone
* HEAT_STACK_PUBLIC_NET Heat stack floating IP pool
* OPENSTACK_API_URL OpenStack API address
* OPENSTACK_API_CREDENTIALS Credentials to the OpenStack API
* OPENSTACK_API_PROJECT OpenStack project to connect to
* OPENSTACK_API_VERSION Version of the OpenStack API (2/3)
*
* SALT_MASTER_CREDENTIALS Credentials to the Salt API
* SALT_MASTER_URL URL of Salt master
*/
common = new com.mirantis.mk.Common()
git = new com.mirantis.mk.Git()
openstack = new com.mirantis.mk.Openstack()
orchestrate = new com.mirantis.mk.Orchestrate()
python = new com.mirantis.mk.Python()
salt = new com.mirantis.mk.Salt()
// Define global variables
def venv
def venvPepper
def outputs = [:]
def ipRegex = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"
def envParams
timeout(time: 12, unit: 'HOURS') {
node("python") {
try {
// Set build-specific variables
venv = "${env.WORKSPACE}/venv"
venvPepper = "${env.WORKSPACE}/venvPepper"
//
// Prepare machines
//
stage ('Create infrastructure') {
// value defaults
envParams = [
'cluster_zone': HEAT_STACK_ZONE,
'cluster_public_net': HEAT_STACK_PUBLIC_NET
]
// no underscore in STACK_NAME
STACK_NAME = STACK_NAME.replaceAll('_', '-')
outputs.put('stack_name', STACK_NAME)
// set description
currentBuild.description = STACK_NAME
// get templates
git.checkoutGitRepository('template', STACK_TEMPLATE_URL, STACK_TEMPLATE_BRANCH, STACK_TEMPLATE_CREDENTIALS)
// create openstack env
openstack.setupOpenstackVirtualenv(venv)
openstackCloud = openstack.createOpenstackEnv(venv,
OPENSTACK_API_URL, OPENSTACK_API_CREDENTIALS,
OPENSTACK_API_PROJECT, "default", "", "default", "3")
openstack.getKeystoneToken(openstackCloud, venv)
// set reclass repo in heat env
try {
envParams.put('cfg_reclass_branch', STACK_RECLASS_BRANCH)
envParams.put('cfg_reclass_address', STACK_RECLASS_ADDRESS)
} catch (MissingPropertyException e) {
common.infoMsg("Property STACK_RECLASS_BRANCH or STACK_RECLASS_ADDRESS not found! Using default values from template.")
}
// launch stack
openstack.createHeatStack(openstackCloud, STACK_NAME, STACK_TEMPLATE, envParams, HEAT_STACK_ENVIRONMENT, venv)
// get SALT_MASTER_URL
saltMasterHost = openstack.getHeatStackOutputParam(openstackCloud, STACK_NAME, 'salt_master_ip', venv)
// check that saltMasterHost is valid
if (!saltMasterHost || !saltMasterHost.matches(ipRegex)) {
common.errorMsg("saltMasterHost is not a valid ip, value is: ${saltMasterHost}")
throw new Exception("saltMasterHost is not a valid ip")
}
currentBuild.description = "${STACK_NAME} ${saltMasterHost}"
SALT_MASTER_URL = "http://${saltMasterHost}:6969"
// Setup virtualenv for pepper
python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
}
stage('Install core infrastructure') {
def staticMgmtNetwork = false
if (common.validInputParam('STATIC_MGMT_NETWORK')) {
staticMgmtNetwork = STATIC_MGMT_NETWORK.toBoolean()
}
orchestrate.installFoundationInfra(venvPepper, staticMgmtNetwork)
if (common.checkContains('STACK_INSTALL', 'kvm')) {
orchestrate.installInfraKvm(venvPepper)
orchestrate.installFoundationInfra(venvPepper, staticMgmtNetwork)
}
orchestrate.validateFoundationInfra(venvPepper)
}
stage('Install Kubernetes infra') {
// configure kubernetes_control_address - save loadbalancer
def awsOutputs = aws.getOutputs(venv, aws_env_vars, STACK_NAME)
common.prettyPrint(awsOutputs)
if (awsOutputs.containsKey('ControlLoadBalancer')) {
salt.runSaltProcessStep(venvPepper, 'I@salt:master', 'reclass.cluster_meta_set', ['kubernetes_control_address', awsOutputs['ControlLoadBalancer']], null, true)
outputs.put('kubernetes_apiserver', 'https://' + awsOutputs['ControlLoadBalancer'])
}
// ensure certificates are generated properly
salt.runSaltProcessStep(venvPepper, 'I@kubernetes:*', 'saltutil.refresh_pillar', [], null, true)
salt.enforceState(venvPepper, 'I@kubernetes:*', ['salt.minion.cert'], true)
orchestrate.installKubernetesInfra(venvPepper)
}
stage('Install Kubernetes control') {
orchestrate.installKubernetesControl(venvPepper)
// collect artifacts (kubeconfig)
writeFile(file: 'kubeconfig', text: salt.getFileContent(venvPepper, 'I@kubernetes:master and *01*', '/etc/kubernetes/admin-kube-config'))
archiveArtifacts(artifacts: 'kubeconfig')
}
stage('Install Kubernetes computes') {
if (common.validInputParam('STACK_COMPUTE_COUNT')) {
if (STACK_COMPUTE_COUNT > 0) {
// get stack info
def scaling_group = aws.getOutputs(venv, aws_env_vars, STACK_NAME, 'ComputesScalingGroup')
//update autoscaling group
aws.updateAutoscalingGroup(venv, aws_env_vars, scaling_group, ["--desired-capacity " + STACK_COMPUTE_COUNT])
// wait for computes to boot up
aws.waitForAutoscalingInstances(venv, aws_env_vars, scaling_group)
sleep(60)
}
}
orchestrate.installKubernetesCompute(venvPepper)
}
stage('Finalize') {
outputsPretty = common.prettify(outputs)
print(outputsPretty)
writeFile(file: 'outputs.json', text: outputsPretty)
archiveArtifacts(artifacts: 'outputs.json')
}
} catch (Throwable e) {
currentBuild.result = 'FAILURE'
throw e
} finally {
if (currentBuild.result == 'FAILURE') {
common.errorMsg("Deploy job FAILED and was not deleted. Please fix the problem and delete stack on you own.")
if (common.validInputParam('SALT_MASTER_URL')) {
common.errorMsg("Salt master URL: ${SALT_MASTER_URL}")
}
}
}
}
}