blob: fe0d0eb93808b3d53741bbfe9d3eecd936b85655 [file] [log] [blame]
Jakub Josef123be7a2016-12-12 16:02:36 +01001import logging
Jakub Josef123be7a2016-12-12 16:02:36 +01002
Adam Tengler70763e02017-08-21 16:50:32 +00003logger = logging.getLogger(__name__)
Jakub Josef123be7a2016-12-12 16:02:36 +01004
5create_node_groovy = u"""\
6import jenkins.model.*
7import hudson.model.*
8import hudson.slaves.*
9import hudson.plugins.sshslaves.*
Jakub Josef123be7a2016-12-12 16:02:36 +010010
Dmitry Burmistrov2a3ba9c2018-03-15 19:22:32 +040011def launcherName = ${launcher}.getClass().getName()
12def retStrategyName = new hudson.slaves.RetentionStrategy.${ret_strategy}().getClass().getName()
13
14
15switch (launcherName) {
16 case 'hudson.slaves.JNLPLauncher':
17 result = Jenkins.instance.slaves.find{
18 it.name == "${name}" &&
19 it.numExecutors == ${num_executors} &&
20 it.nodeDescription == "${desc}" &&
21 it.remoteFS == "${remote_home}" &&
22 it.labelString == "${label}" &&
23 it.mode == Node.Mode.${node_mode} &&
24 it.launcher.tunnel == ("${tunnel}" ?: null) &&
25 it.launcher.vmargs == ("${jvmopts}" ?: null) &&
26 it.launcher.getClass().getName().equals(launcherName) &&
27 it.retentionStrategy.getClass().getName().equals(retStrategyName)
28 }
29 break
30 default:
31 result = Jenkins.instance.slaves.find{
32 it.name == "${name}" &&
33 it.numExecutors == ${num_executors} &&
34 it.nodeDescription == "${desc}" &&
35 it.remoteFS == "${remote_home}" &&
36 it.labelString == "${label}" &&
37 it.mode == Node.Mode.${node_mode} &&
38 it.launcher.jvmOptions == "${jvmopts}" &&
39 it.launcher.getClass().getName().equals(launcherName) &&
40 it.retentionStrategy.getClass().getName().equals(retStrategyName)
41 }
42 break
43}
44
Adam Tengler70763e02017-08-21 16:50:32 +000045if(result){
Dmitry Burmistrov2a3ba9c2018-03-15 19:22:32 +040046 print("EXISTS")
Adam Tengler70763e02017-08-21 16:50:32 +000047}else{
Jakub Josef123be7a2016-12-12 16:02:36 +010048 Slave slave = new DumbSlave(
Adam Tengler70763e02017-08-21 16:50:32 +000049 "${name}",
50 "${desc}",
51 "${remote_home}",
52 "${num_executors}",
53 Node.Mode.${node_mode},
54 "${label}",
55 ${launcher},
56 new RetentionStrategy.${ret_strategy}(),
Jakub Josef123be7a2016-12-12 16:02:36 +010057 new LinkedList())
58 Jenkins.instance.addNode(slave)
Jakub Josef98123ab2016-12-14 14:05:01 +010059 print("CREATED")
Adam Tengler70763e02017-08-21 16:50:32 +000060}
Jakub Josef123be7a2016-12-12 16:02:36 +010061""" # noqa
62
63create_lbl_groovy = u"""\
64hudson = hudson.model.Hudson.instance
65updated = false
Adam Tengler70763e02017-08-21 16:50:32 +000066hudson.slaves.find { slave -> slave.nodeName.equals("${name}")
67 if({append}){
68 slave.labelString = slave.labelString + " " + "${lbl_text}"
69 }else{
70 slave.labelString = "${lbl_text}"
71 }
Jakub Josef123be7a2016-12-12 16:02:36 +010072 updated = true
Adam Tengler70763e02017-08-21 16:50:32 +000073 print "${lbl_text}"
74}
75if(!updated){
Jakub Josef123be7a2016-12-12 16:02:36 +010076 print "FAILED"
Adam Tengler70763e02017-08-21 16:50:32 +000077}
Jakub Josef123be7a2016-12-12 16:02:36 +010078hudson.save()
79""" # noqa
80
Jakub Josef1bb7f442017-05-26 17:02:56 +020081configure_master_groovy = u"""\
82def instance = Jenkins.instance
83def changed = false
84
Adam Tengler70763e02017-08-21 16:50:32 +000085if(Jenkins.instance.numExecutors != ${num_executors}){
86 Jenkins.instance.setNumExecutors(${num_executors})
Jakub Josef1bb7f442017-05-26 17:02:56 +020087 changed = true
Adam Tengler70763e02017-08-21 16:50:32 +000088}
Jakub Josef1bb7f442017-05-26 17:02:56 +020089
Adam Tengler70763e02017-08-21 16:50:32 +000090if(!Jenkins.instance.mode.name.equals(new String("${node_mode}").toUpperCase())){
91 Jenkins.instance.setMode(Node.Mode.${node_mode})
Jakub Josef1bb7f442017-05-26 17:02:56 +020092 changed = true
Adam Tengler70763e02017-08-21 16:50:32 +000093}
Jakub Josef1bb7f442017-05-26 17:02:56 +020094
Adam Tengler70763e02017-08-21 16:50:32 +000095if(!Jenkins.instance.labelString.equals("${labels}")){
96 Jenkins.instance.setLabelString("${labels}")
Jakub Josef1bb7f442017-05-26 17:02:56 +020097 changed = true
Adam Tengler70763e02017-08-21 16:50:32 +000098}
99if(changed){
Jakub Josef1bb7f442017-05-26 17:02:56 +0200100 Jenkins.instance.save()
Jakub Josef7339a002017-06-09 11:33:02 +0200101 print("CREATED")
Adam Tengler70763e02017-08-21 16:50:32 +0000102}else{
Jakub Josef58787542017-06-08 16:59:47 +0200103 print("EXISTS")
Adam Tengler70763e02017-08-21 16:50:32 +0000104}
Jakub Josef1bb7f442017-05-26 17:02:56 +0200105"""
Jakub Josef123be7a2016-12-12 16:02:36 +0100106
Ilya Kharin3d8bffe2017-06-22 17:40:31 +0400107
108def __virtual__():
109 '''
110 Only load if jenkins_common module exist.
111 '''
112 if 'jenkins_common.call_groovy_script' not in __salt__:
113 return (
114 False,
115 'The jenkins_node state module cannot be loaded: '
116 'jenkins_common not found')
117 return True
118
119
Jakub Josef123be7a2016-12-12 16:02:36 +0100120def label(name, lbl_text, append=False):
121 """
122 Jenkins node label state method
123
124 :param name: node name
125 :param lbl_text: label text
126 :returns: salt-specified state dict
127 """
128 test = __opts__['test'] # noqa
129 ret = {
130 'name': name,
131 'changes': {},
132 'result': False,
133 'comment': '',
134 }
135 result = False
136 if test:
137 status = 'CREATED'
138 ret['changes'][name] = status
139 ret['comment'] = 'Label %s %s' % (name, status.lower())
140 else:
141 call_result = __salt__['jenkins_common.call_groovy_script'](
142 create_lbl_groovy, {'name': name, 'lbl_text': lbl_text, 'append': "true" if append else "false"})
Adam Tengler70763e02017-08-21 16:50:32 +0000143 if call_result["code"] == 200 and call_result["msg"].strip(
144 ) == lbl_text:
Jakub Josef123be7a2016-12-12 16:02:36 +0100145 status = "CREATED"
146 ret['changes'][name] = status
147 ret['comment'] = 'Label %s %s ' % (name, status.lower())
148 result = True
149 else:
150 status = 'FAILED'
151 logger.error(
152 "Jenkins label API call failure: %s", call_result["msg"])
153 ret['comment'] = 'Jenkins label API call failure: %s' % (
154 call_result["msg"])
155 ret['result'] = None if test else result
156 return ret
157
158
Adam Tengler70763e02017-08-21 16:50:32 +0000159def present(name, remote_home, launcher, num_executors="1",
160 node_mode="Normal", desc="", labels=[], ret_strategy="Always"):
Jakub Josef123be7a2016-12-12 16:02:36 +0100161 """
162 Jenkins node state method
163
164 :param name: node name
165 :param remote_home: node remote home path
166 :param launcher: launcher dict with type, name, port, username, password
167 :param num_executors: number of node executurs (optional, default 1)
168 :param node_mode: node mode (optional, default Normal)
Jakub Josef98123ab2016-12-14 14:05:01 +0100169 :param desc: node description (optional)
170 :param labels: node labels list (optional)
Jakub Josef123be7a2016-12-12 16:02:36 +0100171 :param ret_strategy: node retention strategy from RetentionStrategy class
172 :returns: salt-specified state dict
173 """
174 test = __opts__['test'] # noqa
175 ret = {
176 'name': name,
177 'changes': {},
178 'result': False,
179 'comment': '',
180 }
181 result = False
182 if test:
183 status = 'CREATED'
184 ret['changes'][name] = status
185 ret['comment'] = 'Node %s %s' % (name, status.lower())
186 else:
Jakub Josef98123ab2016-12-14 14:05:01 +0100187 label_string = " ".join(labels)
188 launcher_string = "new hudson.slaves.JNLPLauncher()"
Dmitry Burmistrov2a3ba9c2018-03-15 19:22:32 +0400189 tunnel_string = ""
190 jvmopts_string = ""
191 if "jvmopts" in launcher:
192 jvmopts_string = launcher["jvmopts"]
Jakub Josef123be7a2016-12-12 16:02:36 +0100193 if launcher:
194 if launcher["type"] == "ssh":
Dmitry Burmistrov2a3ba9c2018-03-15 19:22:32 +0400195 launcher_string = 'new hudson.plugins.sshslaves.SSHLauncher("{}",{},"{}","{}","","{}","","","")'.format(
196 launcher["host"], launcher["port"], launcher["username"],
197 launcher["password"], jvmopts_string)
Jakub Josef123be7a2016-12-12 16:02:36 +0100198 elif launcher["type"] == "jnlp":
Dmitry Burmistrov2a3ba9c2018-03-15 19:22:32 +0400199 if "tunnel" in launcher:
200 tunnel_string = launcher["tunnel"]
201 launcher_string = 'new hudson.slaves.JNLPLauncher("{}","{}")'.format(
202 tunnel_string, jvmopts_string)
Jakub Josef123be7a2016-12-12 16:02:36 +0100203
204 call_result = __salt__['jenkins_common.call_groovy_script'](
205 create_node_groovy,
206 {"name": name,
Jakub Josef95ad9802017-01-17 15:59:00 +0100207 "desc": desc if desc else "",
208 "label": label_string if label_string else "",
209 "remote_home": remote_home if remote_home else "",
210 "num_executors": num_executors if num_executors else "1",
Jakub Josef123be7a2016-12-12 16:02:36 +0100211 "launcher": launcher_string,
Dmitry Burmistrov2a3ba9c2018-03-15 19:22:32 +0400212 "tunnel": tunnel_string,
213 "jvmopts": jvmopts_string,
Jakub Josef123be7a2016-12-12 16:02:36 +0100214 "node_mode": node_mode.upper(),
Jakub Josef95ad9802017-01-17 15:59:00 +0100215 "ret_strategy": ret_strategy if ret_strategy else "Always"})
Adam Tengler70763e02017-08-21 16:50:32 +0000216 if call_result["code"] == 200 and call_result["msg"] in [
217 "CREATED", "EXISTS"]:
Jakub Josef98123ab2016-12-14 14:05:01 +0100218 status = call_result["msg"]
219 if call_result["msg"] == "CREATED":
220 ret['changes'][name] = status
Jakub Josef123be7a2016-12-12 16:02:36 +0100221 ret['comment'] = 'Node %s %s' % (name, status.lower())
222 result = True
223 else:
224 status = 'FAILED'
225 logger.error(
226 "Jenkins node API call failure: %s", call_result["msg"])
227 ret['comment'] = 'Jenkins node API call failure: %s' % (
228 call_result["msg"])
229 ret['result'] = None if test else result
230 return ret
Jakub Josef1bb7f442017-05-26 17:02:56 +0200231
Jakub Josefd2a62032017-06-06 17:53:21 +0200232
233def setup_master(name, num_executors="1", node_mode="Normal", labels=[]):
Jakub Josef1bb7f442017-05-26 17:02:56 +0200234 """
235 Jenkins setup master state method
236
237 :param name: node name (master)
238 :param num_executors: number of executors (optional, default 1)
239 :param node_mode: Node mode (Normal or Exclusive)
Jakub Josefd2a62032017-06-06 17:53:21 +0200240 :param labels: array of labels
Jakub Josef1bb7f442017-05-26 17:02:56 +0200241 :returns: salt-specified state dict
242 """
243 test = __opts__['test'] # noqa
244 ret = {
245 'name': name,
246 'changes': {},
247 'result': False,
248 'comment': '',
249 }
250 result = False
251 if test:
252 status = 'CREATED'
253 ret['changes'][name] = status
Jakub Josefd2a62032017-06-06 17:53:21 +0200254 ret['comment'] = 'Master node %s' % (status.lower())
Jakub Josef1bb7f442017-05-26 17:02:56 +0200255 else:
256 call_result = __salt__['jenkins_common.call_groovy_script'](
Jakub Josef7339a002017-06-09 11:33:02 +0200257 configure_master_groovy, {'num_executors': num_executors, 'labels': " ".join(labels), 'node_mode': node_mode.upper()})
Adam Tengler70763e02017-08-21 16:50:32 +0000258 if call_result["code"] == 200 and call_result["msg"] in [
259 "CREATED", "EXISTS"]:
Jakub Josef58787542017-06-08 16:59:47 +0200260 status = call_result["msg"]
261 if status == "CREATED":
262 ret['changes'][name] = status
263 ret['comment'] = 'Master node configuration %s ' % (status.lower())
Jakub Josef1bb7f442017-05-26 17:02:56 +0200264 result = True
265 else:
266 status = 'FAILED'
267 logger.error(
268 "Jenkins master configure API call failure: %s", call_result["msg"])
269 ret['comment'] = 'Jenkins master configure API call failure: %s' % (
270 call_result["msg"])
271 ret['result'] = None if test else result
Jakub Josefd2a62032017-06-06 17:53:21 +0200272 return ret