-
Notifications
You must be signed in to change notification settings - Fork 46
/
deploy-heat-k8s-kqueen-pipeline.groovy
179 lines (148 loc) · 7.5 KB
/
deploy-heat-k8s-kqueen-pipeline.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/**
* 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}")
}
}
}
}
}