blob: 19c6816e751a25105dbd893c38b7421b3ffaeaf5 [file] [log] [blame]
Jakub Josef3947b062018-01-10 13:04:13 +01001/**
2 * Helper pipeline for AWS deployments from kqueen
3 *
4 * Expected parameters:
5 * STACK_NAME Infrastructure stack name
6 * STACK_TEMPLATE File with stack template
7 *
8 * STACK_TEMPLATE_URL URL to git repo with stack templates
9 * STACK_TEMPLATE_CREDENTIALS Credentials to the templates repo
10 * STACK_TEMPLATE_BRANCH Stack templates repo branch
11 * STACK_COMPUTE_COUNT Number of compute nodes to launch
12 *
13 * AWS_STACK_REGION CloudFormation AWS region
14 * AWS_API_CREDENTIALS AWS Access key ID with AWS secret access key
15 * AWS_SSH_KEY AWS key pair name (used for SSH access)
16 *
17 * SALT_MASTER_CREDENTIALS Credentials to the Salt API
18 * SALT_MASTER_URL URL of Salt master
19 */
20
21common = new com.mirantis.mk.Common()
22git = new com.mirantis.mk.Git()
23aws = new com.mirantis.mk.Aws()
24orchestrate = new com.mirantis.mk.Orchestrate()
25python = new com.mirantis.mk.Python()
26salt = new com.mirantis.mk.Salt()
27
28// Define global variables
29def venv
30def venvPepper
31def outputs = [:]
32
33def ipRegex = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"
34def aws_env_vars
35node("python") {
36 try {
37 // Set build-specific variables
38 venv = "${env.WORKSPACE}/venv"
39 venvPepper = "${env.WORKSPACE}/venvPepper"
40
41 //
42 // Prepare machines
43 //
44 stage ('Create infrastructure') {
45
46 outputs.put('stack_type', "aws")
47 // setup environment
48 aws.setupVirtualEnv(venv)
49 // set aws_env_vars
50 aws_env_vars = aws.getEnvVars(AWS_API_CREDENTIALS, AWS_STACK_REGION)
51 // We just use STACK_NAME from param
52 currentBuild.description = STACK_NAME
53 outputs.put('stack_name', STACK_NAME)
54
55 // get templates
56 git.checkoutGitRepository('template', STACK_TEMPLATE_URL, STACK_TEMPLATE_BRANCH, STACK_TEMPLATE_CREDENTIALS)
57
58 // start stack
59 def stack_params = [
60 "ParameterKey=KeyName,ParameterValue=" + AWS_SSH_KEY,
61 "ParameterKey=CmpNodeCount,ParameterValue=" + STACK_COMPUTE_COUNT
62 ]
63 def template_file = 'cfn/' + STACK_TEMPLATE + '.yml'
64 aws.createStack(venv, aws_env_vars, template_file, STACK_NAME, stack_params)
65
66 // wait for stack to be ready
67 aws.waitForStatus(venv, aws_env_vars, STACK_NAME, 'CREATE_COMPLETE')
68
69 // get outputs
70 saltMasterHost = aws.getOutputs(venv, aws_env_vars, STACK_NAME, 'SaltMasterIP')
71
72 // check that saltMasterHost is valid
73 if (!saltMasterHost || !saltMasterHost.matches(ipRegex)) {
74 common.errorMsg("saltMasterHost is not a valid ip, value is: ${saltMasterHost}")
75 throw new Exception("saltMasterHost is not a valid ip")
76 }
77
78 currentBuild.description = "${STACK_NAME} ${saltMasterHost}"
79 SALT_MASTER_URL = "http://${saltMasterHost}:6969"
80
81 outputs.put('salt_api', SALT_MASTER_URL)
82
83 // Setup virtualenv for pepper
84 python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
85 }
86
87 stage('Install core infrastructure') {
88 def staticMgmtNetwork = false
89 if (common.validInputParam('STATIC_MGMT_NETWORK')) {
90 staticMgmtNetwork = STATIC_MGMT_NETWORK.toBoolean()
91 }
92 orchestrate.installFoundationInfra(venvPepper, staticMgmtNetwork)
93
94 if (common.checkContains('STACK_INSTALL', 'kvm')) {
95 orchestrate.installInfraKvm(venvPepper)
96 orchestrate.installFoundationInfra(venvPepper, staticMgmtNetwork)
97 }
98
99 orchestrate.validateFoundationInfra(venvPepper)
100 }
101 stage('Install Kubernetes infra') {
102 if (STACK_TYPE == 'aws') {
103 // configure kubernetes_control_address - save loadbalancer
104 def awsOutputs = aws.getOutputs(venv, aws_env_vars, STACK_NAME)
105 common.prettyPrint(awsOutputs)
106 if (awsOutputs.containsKey('ControlLoadBalancer')) {
107 salt.runSaltProcessStep(venvPepper, 'I@salt:master', 'reclass.cluster_meta_set', ['kubernetes_control_address', awsOutputs['ControlLoadBalancer']], null, true)
108 outputs.put('kubernetes_apiserver', 'https://' + awsOutputs['ControlLoadBalancer'])
109 }
110 }
111
112 // ensure certificates are generated properly
113 salt.runSaltProcessStep(venvPepper, '*', 'saltutil.refresh_pillar', [], null, true)
114 salt.enforceState(venvPepper, '*', ['salt.minion.cert'], true)
115
116 orchestrate.installKubernetesInfra(venvPepper)
117 }
118
119 stage('Install Kubernetes control') {
120 orchestrate.installKubernetesControl(venvPepper)
121
122 // collect artifacts (kubeconfig)
123 writeFile(file: 'kubeconfig', text: salt.getFileContent(venvPepper, 'I@kubernetes:master and *01*', '/etc/kubernetes/admin-kube-config'))
124 archiveArtifacts(artifacts: 'kubeconfig')
125 }
126
127 stage('Install Kubernetes computes') {
128 if (common.validInputParam('STACK_COMPUTE_COUNT')) {
129 if (STACK_COMPUTE_COUNT > 0) {
130 // get stack info
131 def scaling_group = aws.getOutputs(venv, aws_env_vars, STACK_NAME, 'ComputesScalingGroup')
132
133 //update autoscaling group
134 aws.updateAutoscalingGroup(venv, aws_env_vars, scaling_group, ["--desired-capacity " + STACK_COMPUTE_COUNT])
135
136 // wait for computes to boot up
137 aws.waitForAutoscalingInstances(venv, aws_env_vars, scaling_group)
138 sleep(60)
139 }
140 }
141
142 orchestrate.installKubernetesCompute(venvPepper)
143 }
144
145 stage('Finalize') {
146 outputsPretty = common.prettify(outputs)
147 print(outputsPretty)
148 writeFile(file: 'outputs.json', text: outputsPretty)
149 archiveArtifacts(artifacts: 'outputs.json')
150 }
151
152 } catch (Throwable e) {
153 currentBuild.result = 'FAILURE'
154 throw e
155 } finally {
156 if (currentBuild.result == 'FAILURE') {
157 common.errorMsg("Deploy job FAILED and was not deleted. Please fix the problem and delete stack on you own.")
158
159 if (common.validInputParam('SALT_MASTER_URL')) {
160 common.errorMsg("Salt master URL: ${SALT_MASTER_URL}")
161 }
162 }
163 }
164}
165
166